[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