[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