Versionning problem in case of autoFlush required inside an "onSave"
interceptor
--------------------------------------------------------------------------------
Key: HHH-6808
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-6808
Project: Hibernate Core
Issue Type: Bug
Components: entity-manager
Affects Versions: 3.5.6
Environment: Hibernate 3.5.6, Oracle
Reporter: Romain Fromi
I have an interceptor "onSave" for an Entity.
I try to make a query with hibernate inside this onSave.
The following exception is thrown :
java.lang.NullPointerException
at org.hibernate.type.IntegerType.next(IntegerType.java:82)
at org.hibernate.engine.Versioning.increment(Versioning.java:131)
at
org.hibernate.event.def.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:406)
at
org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:296)
at
org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:155)
at
org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at
org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1175)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1699)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
at
org.springframework.orm.hibernate3.HibernateTemplate$36.doInHibernate(HibernateTemplate.java:1056)
at
org.springframework.orm.hibernate3.HibernateTemplate$36.doInHibernate(HibernateTemplate.java:1)
at
org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at
org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
...
As you can see, my query triggers an auto flush, because I try to read some objects
related to the object currently saved (I cannot access these related objects another way,
some relations are not bidirectionnal).
During this auto flush, I have a null pointer inside Versioning.increment because the
EntityEntry has a null version, whereas my entity has a version.
I think that the version inside my own entity is not already reported inside the
EntityEntry - the proof is in the stack trace before the onSave call:
...
at
org.hibernate.event.def.AbstractSaveEventListener.substituteValuesIfNecessary(AbstractSaveEventListener.java:414)
at
org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293)
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:677)
...
As you can see, AbstractSaveEventListener.substituteValuesIfNecessary calls my method. But
this method also process versionning :
398 /**
399 * Perform any property value substitution that is necessary
400 * (interceptor callback, version initialization...)
401 *
402 * @param entity The entity
403 * @param id The entity identifier
404 * @param values The snapshot entity state
405 * @param persister The entity persister
406 * @param source The originating session
407 *
408 * @return True if the snapshot state changed such that
409 * reinjection of the values into the entity is required.
410 */
411 protected boolean substituteValuesIfNecessary(
412 Object entity,
413 Serializable id,
414 Object[] values,
415 EntityPersister persister,
416 SessionImplementor source) {
417 boolean substitute = source.getInterceptor().onSave(
418 entity,
419 id,
420 values,
421 persister.getPropertyNames(),
422 persister.getPropertyTypes()
423 );
424
425 //keep the existing version number in the case of replicate!
426 if ( persister.isVersioned() ) {
427 substitute = Versioning.seedVersion(
428 values,
429 persister.getVersionProperty(),
430 persister.getVersionType(),
431 source
432 ) || substitute;
433 }
434 return substitute;
435 }
"Versioning.seedVersion" is called after
"source.getInterceptor().onSave"
Maybe the version should have already been reported inside the EntityEntry when calling
onSave ?
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira