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

Pavol Zibrita (JIRA) noreply at atlassian.com
Sat Oct 6 15:41:38 EDT 2007


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