[hibernate-issues] [Hibernate-JIRA] Created: (HHH-5039) Entity added instead of replaced in StateFullPersistenceContext during an update
Ed Bras (JIRA)
noreply at atlassian.com
Thu Mar 25 07:25:37 EDT 2010
Entity added instead of replaced in StateFullPersistenceContext during an update
--------------------------------------------------------------------------------
Key: HHH-5039
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5039
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.3.2
Environment: Windows 7
Reporter: Ed Bras
Hibernate bug (version: 3.3.2):
Entity added instead of replaced in StateFullPersistenceContext during an update.
Exception that occurs (only the interesting parts):
----
Caused by: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.bv.core.domain.category.impl.IncomeInfoDefault.wage
at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:58)
at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:87)
at org.hibernate.type.ComponentType.getPropertyValue(ComponentType.java:366)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getComponentValue(AbstractEntityTuplizer.java:335)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer.java:306)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValue(AbstractEntityPersister.java:3600)
at org.hibernate.engine.StatefulPersistenceContext.isFoundInParent(StatefulPersistenceContext.java:1186)
at org.hibernate.engine.StatefulPersistenceContext.getOwnerId(StatefulPersistenceContext.java:1113)
at org.hibernate.property.BackrefPropertyAccessor$BackrefGetter.getForInsert(BackrefPropertyAccessor.java:139)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValuesToInsert(AbstractEntityTuplizer.java:287)
at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValuesToInsert(PojoEntityTuplizer.java:256)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValuesToInsert(AbstractEntityPersister.java:3677)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:241)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:292)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:240)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:320)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:266)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:243)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.Cascade.cascadeComponent(Cascade.java:222)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:203)
at org.hibernate.engine.Cascade.cascadeComponent(Cascade.java:222)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:203)
at org.hibernate.engine.Cascade.cascade(Cascade.java:154)
at org.hibernate.engine.Cascade.cascade(Cascade.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:380)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:352)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:246)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:112)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at com.ited.hibernate.impl.DaoHibernateBase.saveOrUpdateEntity(DaoHibernateBase.java:55)
at com.ited.hibernate.impl.DaoHibernateBase.saveOrUpdateEntity(DaoHibernateBase.java:1)
at sun.reflect.GeneratedMethodAccessor18.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy12.saveOrUpdateEntity(Unknown Source)
at sun.reflect.GeneratedMethodAccessor18.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.ited.lang.proxy.intern.impl.MethodInvokerDefault.invokeMethod(MethodInvokerDefault.java:79)
at com.ited.lang.proxy.intern.impl.MethodInvokerDefault.invoke(MethodInvokerDefault.java:69)
at com.ited.lang.proxy.impl.ProxyMethodDefault.invoke(ProxyMethodDefault.java:369)
at com.ited.lang.proxy.impl.ProxyMethodDefault.invoke(ProxyMethodDefault.java:174)
at com.ited.persist.ProxyMethodDaoHibernate.invoke(ProxyMethodDaoHibernate.java:56)
... 62 more
Caused by: java.lang.NullPointerException
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
at java.lang.reflect.Field.get(Field.java:358)
at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:55)
... 126 more
----
Sorry for not having a test case, but it occurs under a combination of curcumstances and is a bit complex.
I do the following:
Object graph:
Entity E1 has an association to E2 with a cascade update/delete. E2 is dependent on E1 and should be a Value type object, but I made it a entity for performance reasons to get lazy loading. E1 and E2 share the same String id (UUID).
E2 has 2 other Value type associations V1 and V2.
Actions:
I create a new E1 with E2 and no V1 and V2, and saveOrUpdate this in one transaction to the database.
Then I create a NEW E2 (with the same Id as the old E1), add V1 and V2 to E2 and saveOrUpdate only E2 and get the exception above.
BTW: I changed my code now such that E2 can't be replaced by another version with the same ID, which I think is also more "healhty", but I think that still Hibernate should be able to deal with this situation.
What happens in the Hibernate code:
When I saveOrUpdate E2, it will first call StatefulPersistenceContext.addEntry from DefaultSaveOrUpdateEventListener.performUpdate
The call trace of this call:
-------------
StatefulPersistenceContext.addEntry(Object, Status, Object[], Object, Serializable, Object, LockMode, boolean, EntityPersister, boolean, boolean) line: 481
StatefulPersistenceContext.addEntity(Object, Status, Object[], EntityKey, Object, LockMode, boolean, EntityPersister, boolean, boolean) line: 433
DefaultSaveOrUpdateEventListener.performUpdate(SaveOrUpdateEvent, Object, EntityPersister) line: 330
DefaultSaveOrUpdateEventListener.entityIsDetached(SaveOrUpdateEvent) line: 246
DefaultSaveOrUpdateEventListener.performSaveOrUpdate(SaveOrUpdateEvent) line: 112
DefaultSaveOrUpdateEventListener.onSaveOrUpdate(SaveOrUpdateEvent) line: 93
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 535
SessionImpl.saveOrUpdate(String, Object) line: 527
SessionImpl.saveOrUpdate(Object) line: 523
DaoHibernateBase.saveOrUpdateEntity(Serializable) line: 55
DaoHibernateBase.saveOrUpdateEntity(Object) line: 1
GeneratedMethodAccessor18.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
-------------
Because this entity is already present (because the old Id of E2 was used) in entityEntries it will NOT be added, leaving the old one in the entityEntries (idea: maybe Hibernate should throw an exception in this case... ).
Hibernate will then perform cascading updates of V1 and V2. It will then call StatefulPersistenceContext.getOwnerId and will retrieve the OLD E2 from entityEntries. Because the old E2 has no V1 and V2 it will throw a null pointer exception when using this one to access the field.
The call trace just before the exception:
-------------
Thread [main] (Suspended (breakpoint at line 58 in DirectPropertyAccessor$DirectGetter))
DirectPropertyAccessor$DirectGetter.get(Object) line: 58
PojoComponentTuplizer(AbstractComponentTuplizer).getPropertyValue(Object, int) line: 87
ComponentType.getPropertyValue(Object, int, EntityMode) line: 366
PojoEntityTuplizer(AbstractEntityTuplizer).getComponentValue(ComponentType, Object, String) line: 335
PojoEntityTuplizer(AbstractEntityTuplizer).getPropertyValue(Object, String) line: 306
SingleTableEntityPersister(AbstractEntityPersister).getPropertyValue(Object, String, EntityMode) line: 3600
StatefulPersistenceContext.isFoundInParent(String, Object, EntityPersister, CollectionPersister, Object) line: 1186
StatefulPersistenceContext.getOwnerId(String, String, Object, Map) line: 1113
BackrefPropertyAccessor$BackrefGetter.getForInsert(Object, Map, SessionImplementor) line: 139
PojoEntityTuplizer(AbstractEntityTuplizer).getPropertyValuesToInsert(Object, Map, SessionImplementor) line: 287
PojoEntityTuplizer.getPropertyValuesToInsert(Object, Map, SessionImplementor) line: 256
SingleTableEntityPersister(AbstractEntityPersister).getPropertyValuesToInsert(Object, Map, SessionImplementor) line: 3677
DefaultSaveOrUpdateEventListener(AbstractSaveEventListener).performSaveOrReplicate(Object, EntityKey, EntityPersister, boolean, Object, EventSource, boolean) line: 290
DefaultSaveOrUpdateEventListener(AbstractSaveEventListener).performSave(Object, Serializable, EntityPersister, boolean, Object, EventSource, boolean) line: 204
DefaultSaveOrUpdateEventListener(AbstractSaveEventListener).saveWithGeneratedId(Object, String, Object, EventSource, boolean) line: 144
DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(SaveOrUpdateEvent) line: 210
DefaultSaveOrUpdateEventListener.entityIsTransient(SaveOrUpdateEvent) line: 195
DefaultSaveOrUpdateEventListener.performSaveOrUpdate(SaveOrUpdateEvent) line: 117
DefaultSaveOrUpdateEventListener.onSaveOrUpdate(SaveOrUpdateEvent) line: 93
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 535
SessionImpl.saveOrUpdate(String, Object) line: 527
CascadingAction$5.cascade(EventSource, Object, String, Object, boolean) line: 241
Cascade.cascadeToOne(Object, Type, CascadeStyle, Object, boolean) line: 292
Cascade.cascadeAssociation(Object, Type, CascadeStyle, Object, boolean) line: 240
Cascade.cascadeProperty(Object, Type, CascadeStyle, Object, boolean) line: 193
Cascade.cascadeCollectionElements(Object, CollectionType, CascadeStyle, Type, Object, boolean) line: 320
Cascade.cascadeCollection(Object, CascadeStyle, Object, CollectionType) line: 266
Cascade.cascadeAssociation(Object, Type, CascadeStyle, Object, boolean) line: 243
Cascade.cascadeProperty(Object, Type, CascadeStyle, Object, boolean) line: 193
Cascade.cascadeComponent(Object, AbstractComponentType, Object) line: 222
Cascade.cascadeProperty(Object, Type, CascadeStyle, Object, boolean) line: 203
Cascade.cascadeComponent(Object, AbstractComponentType, Object) line: 222
Cascade.cascadeProperty(Object, Type, CascadeStyle, Object, boolean) line: 203
Cascade.cascade(EntityPersister, Object, Object) line: 154
Cascade.cascade(EntityPersister, Object) line: 121
DefaultSaveOrUpdateEventListener.cascadeOnUpdate(SaveOrUpdateEvent, EntityPersister, Object) line: 380
DefaultSaveOrUpdateEventListener.performUpdate(SaveOrUpdateEvent, Object, EntityPersister) line: 352
DefaultSaveOrUpdateEventListener.entityIsDetached(SaveOrUpdateEvent) line: 246
DefaultSaveOrUpdateEventListener.performSaveOrUpdate(SaveOrUpdateEvent) line: 112
DefaultSaveOrUpdateEventListener.onSaveOrUpdate(SaveOrUpdateEvent) line: 93
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 535
SessionImpl.saveOrUpdate(String, Object) line: 527
SessionImpl.saveOrUpdate(Object) line: 523
DaoHibernateBase.saveOrUpdateEntity(Serializable) line: 55
DaoHibernateBase.saveOrUpdateEntity(Object) line: 1
GeneratedMethodAccessor18.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
-------------
Hope it contains enough information to deal with it.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the hibernate-issues
mailing list