[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-2881) PersistantBag.initializeFromCache can be intercepted by CollectionLoadContext.getLoadingCollection and so corrupt the collection

Gail Badner (JIRA) noreply at atlassian.com
Mon Oct 8 13:10:39 EDT 2007


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-2881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_28381 ] 

Gail Badner commented on HHH-2881:
----------------------------------

Please attach a runnable test case (Java + mapping).

> PersistantBag.initializeFromCache can be intercepted by CollectionLoadContext.getLoadingCollection and so corrupt the collection
> --------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HHH-2881
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2881
>             Project: Hibernate3
>          Issue Type: Bug
>         Environment: Hibernate Entity Manager 3.3.1 GA, oracle,
>            Reporter: Pavol Zibrita
>
> It can occur that while PersistenBag.initializeFromCache is called to populate the collection from cache, the collection is populated also from CollectionLoadContext.getLoadingCollection, and so, the collection is filled with more data than needed. As the initializeFromCache uses direct access to the property this.bag, it will continue loading the collection. Here is the stack trace of what happens:
> PersistentBag.beforeInitialize(CollectionPersister, int) line: xx //here is the same collection reinitialized again, and loaded again   
>    CollectionLoadContext.getLoadingCollection(CollectionPersister, Serializable) line: 127   
>    EntityLoader(Loader).readCollectionElement(Object, Serializable, CollectionPersister, CollectionAliases, ResultSet, SessionImplementor) line: 1003   
>    EntityLoader(Loader).readCollectionElements(Object[], ResultSet, SessionImplementor) line: 646   
>    EntityLoader(Loader).getRowFromResultSet(ResultSet, SessionImplementor, QueryParameters, LockMode[], EntityKey, List, EntityKey[], boolean) line: 591   
>    EntityLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean) line: 701   
>    EntityLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 236   
>    EntityLoader(Loader).loadEntity(SessionImplementor, Object, Type, Object, String, Serializable, EntityPersister) line: 1860   
>    EntityLoader(AbstractEntityLoader).load(SessionImplementor, Object, Object, Serializable) line: 48   
>    EntityLoader(AbstractEntityLoader).load(Serializable, Object, SessionImplementor) line: 42   
>    SingleTableEntityPersister(AbstractEntityPersister).load(Serializable, Object, LockMode, SessionImplementor) line: 3044   
>    DefaultLoadEventListener.loadFromDatasource(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 395   
>    DefaultLoadEventListener.doLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 375   
>    DefaultLoadEventListener.load(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 139   
>    DefaultLoadEventListener.proxyOrLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 195   
>    DefaultLoadEventListener.onLoad(LoadEvent, LoadEventListener$LoadType) line: 103   
>    SessionImpl.fireLoad(LoadEvent, LoadEventListener$LoadType) line: 878   
>    SessionImpl.internalLoad(String, Serializable, boolean, boolean) line: 846   
>    ManyToOneType(EntityType).resolveIdentifier(Serializable, SessionImplementor) line: 557   
>    ManyToOneType.assemble(Serializable, SessionImplementor, Object) line: 196   
>    TypeFactory.assemble(Serializable[], Type[], SessionImplementor, Object) line: 420   
>    CacheEntry.assemble(Serializable[], Object, Serializable, EntityPersister, Interceptor, EventSource) line: 96   
>    CacheEntry.assemble(Object, Serializable, EntityPersister, Interceptor, EventSource) line: 82   
>    DefaultLoadEventListener.assembleCacheEntry(CacheEntry, Serializable, EntityPersister, LoadEvent) line: 553   
>    DefaultLoadEventListener.loadFromSecondLevelCache(LoadEvent, EntityPersister, LoadEventListener$LoadType) line: 508   
>    DefaultLoadEventListener.doLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 357   
>    DefaultLoadEventListener.load(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 139   
>    DefaultLoadEventListener.proxyOrLoad(LoadEvent, EntityPersister, EntityKey, LoadEventListener$LoadType) line: 195   
>    DefaultLoadEventListener.onLoad(LoadEvent, LoadEventListener$LoadType) line: 103   
>    SessionImpl.fireLoad(LoadEvent, LoadEventListener$LoadType) line: 878   
>    SessionImpl.internalLoad(String, Serializable, boolean, boolean) line: 846   
>    ManyToOneType(EntityType).resolveIdentifier(Serializable, SessionImplementor) line: 557   
>    ManyToOneType.assemble(Serializable, SessionImplementor, Object) line: 196   
>    PersistentBag.initializeFromCache(CollectionPersister, Serializable, Object) line: xxx //NOW HERE IS THE Bag initializing from cache, it fails, see top of the stack!!   
>    CollectionCacheEntry.assemble(PersistentCollection, CollectionPersister, Object) line: 35   
>    DefaultInitializeCollectionEventListener.initializeCollectionFromCache(Serializable, CollectionPersister, PersistentCollection, SessionImplementor) line: 130   
>    DefaultInitializeCollectionEventListener.onInitializeCollection(InitializeCollectionEvent) line: 48   
>    SessionImpl.initializeCollection(PersistentCollection, boolean) line: 1716   
>    PersistentBag(AbstractPersistentCollection).forceInitialization() line: 454   
>    StatefulPersistenceContext.initializeNonLazyCollections() line: 794   
>    QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean) line: 241   
>    QueryLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2220   
>    QueryLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line: 2104   
>    QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2099   
>    QueryLoader.list(SessionImplementor, QueryParameters) line: 378   
>    QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 338   
>    HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 172   
>    SessionImpl.list(String, QueryParameters) line: 1121   
>    QueryImpl.list() line: 79   
>    QueryImpl.getResultList() line: 66   
>    //some stack before, uninportant 
> Small fix to the PersistantBag has resolved this issue, however I cannot tell if it is correct by some hibernate principles:
> 	public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
> 	throws HibernateException {
> 		Serializable[] array = (Serializable[]) disassembled;
> 		int size = array.length;
> 		List<Object> elements = new ArrayList<Object>(size);
> 		for ( int i = 0; i < size; i++ ) {
> 			Object element = persister.getElementType().assemble( array[i], getSession(), owner );
> 			if ( element!=null ) {
> 				elements.add( element );
> 			}
> 		}
> 		beforeInitialize( persister, size );
> 		for ( Object element : elements ) {
> 			this.bag.add( element );
> 		}
> 	}
> Difference is, before the this.bag.add(element) was called in first cycle, where the line of getting the element could cause reinitializing the collection and filling it up. There are various possibilities how to fix the problem, but I don't know if the fix is at the right place!
>     

-- 
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