[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-6808) Versionning problem in case of autoFlush required inside an "onSave" interceptor
Romain Fromi (JIRA)
noreply at atlassian.com
Mon Nov 7 09:27:19 EST 2011
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-6808?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=44266#comment-44266 ]
Romain Fromi commented on HHH-6808:
-----------------------------------
During the research I made, I saw this entry : https://hibernate.onjira.com/browse/HHH-3030
And this post : https://forum.hibernate.org/viewtopic.php?f=1&t=995904
So I am not the first one falling into this pit !
> 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
> Labels: autoFlush, interceptor, versionning
>
> 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
More information about the hibernate-issues
mailing list