We are currently trying to upgrade a project from Hibernate 5 to 6, which
When using an {{@Embedded}} value object that has a collection with orphan removal, trying to delete the root entity throws a {{PropertyAccessException}}. The same scenario used to work without issue in Hibernate 5.
I have prepared an [example test |https://github.com/cwatzl/hhh-16007]project to demonstrate the issue.
Model:
{code:java}@Entity public class Parent { @Id private final String id; @Embedded private final Child child;
// ... ctors & accessors ... }
@Embeddable public class Child { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) private final List<Grandchild> grandchildren = new ArrayList<>();
// ... ctors & accessors ... }
@Entity public class Grandchild { @Id private final String id;
// .. ctors & accessors ... }{code}
Test case:
{code:java}var parent = new Parent("123", new Child(List.of(new Grandchild("xyz")))); entityManager.persist(parent); entityManager.flush(); entityManager.clear(); entityManager.remove(entityManager.getReference(Parent.class, "123")); entityManager.flush(); // throws PersistenceException{code}
*Exception thrown*
{noformat}jakarta.persistence.PersistenceException: Converting `org.hibernate.property.access.spi.PropertyAccessException` to JPA `PersistenceException` : Error accessing field [private final java.lang.String org.hibernate.bugs.model.Parent.id] by reflection for persistent property [org.hibernate.bugs.model.Parent#id] : org.hibernate.bugs.model.Child@77c66a4f
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:165) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:175) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:182) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1429) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1411) at org.hibernate.bugs.JPAUnitTestCase.hhh123Test(JPAUnitTestCase.java:47) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private final java.lang.String org.hibernate.bugs.model.Parent.id] by reflection for persistent property [org.hibernate.bugs.model.Parent#id] : org.hibernate.bugs.model.Child@77c66a4f at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:48) at org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl.getIdentifier(BasicEntityIdentifierMappingImpl.java:147) at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:5254) at org.hibernate.engine.internal.Collections.processDereferencedCollection(Collections.java:70) at org.hibernate.engine.internal.Collections.processUnreachableCollection(Collections.java:49) at org.hibernate.event.internal.AbstractFlushingEventListener.lambda$flushCollections$1(AbstractFlushingEventListener.java:236) at org.hibernate.engine.internal.StatefulPersistenceContext.forEachCollectionEntry(StatefulPersistenceContext.java:1127) at org.hibernate.event.internal.AbstractFlushingEventListener.flushCollections(AbstractFlushingEventListener.java:233) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:91) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1425) ... 31 more Caused by: java.lang.IllegalArgumentException: Can not set final java.lang.String field org.hibernate.bugs.model.Parent.id to org.hibernate.bugs.model.Child at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38) at java.base/java.lang.reflect.Field.get(Field.java:425) at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:44) ... 42 more{noformat}
Of particular interest is this message:
{noformat}Can not set final java.lang.String field org.hibernate.bugs.model.Parent.id to org.hibernate.bugs.model.Child{noformat}
Apparently, for some reason, {{AbstractEntityPersister}} is trying to reflectively access the id property of the Parent entity but applies the getter to the embeddable child value type, which makes no sense. |
|