Code example for BatchFetchQueue

Methods: addBatchLoadableCollection

0
		} 
		return batchFetchQueue; 
	} 
 
	public void clear() { 
		for ( Object o : proxiesByKey.values() ) { 
			final LazyInitializer li = ((HibernateProxy) o).getHibernateLazyInitializer(); 
			li.unsetSession(); 
		} 
		Map.Entry[] collectionEntryArray = IdentityMap.concurrentEntries( collectionEntries ); 
		for ( Map.Entry aCollectionEntryArray : collectionEntryArray ) { 
			((PersistentCollection) aCollectionEntryArray.getKey()).unsetSession( getSession() ); 
		} 
		arrayHolders.clear(); 
		entitiesByKey.clear(); 
		entitiesByUniqueKey.clear(); 
		entityEntries.clear(); 
		parentsByChild.clear(); 
		entitySnapshotsByKey.clear(); 
		collectionsByKey.clear(); 
		collectionEntries.clear(); 
		if ( unownedCollections != null ) { 
			unownedCollections.clear(); 
		} 
		proxiesByKey.clear(); 
		nullifiableEntityKeys.clear(); 
		if ( batchFetchQueue != null ) { 
			batchFetchQueue.clear(); 
		} 
		// defaultReadOnly is unaffected by clear() 
		hasNonReadOnlyEntities = false; 
		if ( loadContexts != null ) { 
			loadContexts.cleanup(); 
		} 
	} 
 
	/** 
	 * {@inheritDoc} 
	 */ 
	public boolean isDefaultReadOnly() { 
		return defaultReadOnly; 
	} 
 
	/** 
	 * {@inheritDoc} 
	 */ 
	public void setDefaultReadOnly(boolean defaultReadOnly) { 
		this.defaultReadOnly = defaultReadOnly; 
	} 
 
	public boolean hasNonReadOnlyEntities() { 
		return hasNonReadOnlyEntities; 
	} 
 
	public void setEntryStatus(EntityEntry entry, Status status) { 
		entry.setStatus(status); 
		setHasNonReadOnlyEnties(status); 
	} 
 
	private void setHasNonReadOnlyEnties(Status status) { 
		if ( status==Status.DELETED || status==Status.MANAGED || status==Status.SAVING ) { 
			hasNonReadOnlyEntities = true; 
		} 
	} 
 
	public void afterTransactionCompletion() { 
		cleanUpInsertedKeysAfterTransaction(); 
		// Downgrade locks 
		for ( Object o : entityEntries.values() ) { 
			((EntityEntry) o).setLockMode( LockMode.NONE ); 
		} 
	} 
 
	/** 
	 * Get the current state of the entity as known to the underlying 
	 * database, or null if there is no corresponding row 
	 */ 
	public Object[] getDatabaseSnapshot(Serializable id, EntityPersister persister) 
	throws HibernateException { 
		final EntityKey key = session.generateEntityKey( id, persister ); 
		Object cached = entitySnapshotsByKey.get(key); 
		if (cached!=null) { 
			return cached==NO_ROW ? null : (Object[]) cached; 
		} 
		else { 
			Object[] snapshot = persister.getDatabaseSnapshot( id, session ); 
			entitySnapshotsByKey.put( key, snapshot==null ? NO_ROW : snapshot ); 
			return snapshot; 
		} 
	} 
 
	public Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister) 
	throws HibernateException { 
		if ( !persister.hasNaturalIdentifier() ) { 
			return null; 
		} 
 
		// if the natural-id is marked as non-mutable, it is not retrieved during a 
		// normal database-snapshot operation... 
		int[] props = persister.getNaturalIdentifierProperties(); 
		boolean[] updateable = persister.getPropertyUpdateability(); 
		boolean allNatualIdPropsAreUpdateable = true; 
		for ( int i = 0; i < props.length; i++ ) { 
			if ( !updateable[ props[i] ] ) { 
				allNatualIdPropsAreUpdateable = false; 
				break; 
			} 
		} 
 
		if ( allNatualIdPropsAreUpdateable ) { 
			// do this when all the properties are updateable since there is 
			// a certain likelihood that the information will already be 
			// snapshot-cached. 
			Object[] entitySnapshot = getDatabaseSnapshot( id, persister ); 
			if ( entitySnapshot == NO_ROW ) { 
				return null; 
			} 
			Object[] naturalIdSnapshot = new Object[ props.length ]; 
			for ( int i = 0; i < props.length; i++ ) { 
				naturalIdSnapshot[i] = entitySnapshot[ props[i] ]; 
			} 
			return naturalIdSnapshot; 
		} 
		else { 
			return persister.getNaturalIdentifierSnapshot( id, session ); 
		} 
	} 
 
	/** 
	 * Retrieve the cached database snapshot for the requested entity key. 
	 * <p/> 
	 * This differs from {@link #getDatabaseSnapshot} is two important respects:<ol> 
	 * <li>no snapshot is obtained from the database if not already cached</li> 
	 * <li>an entry of {@link #NO_ROW} here is interpretet as an exception</li> 
	 * </ol> 
	 * @param key The entity key for which to retrieve the cached snapshot 
	 * @return The cached snapshot 
	 * @throws IllegalStateException if the cached snapshot was == {@link #NO_ROW}. 
	 */ 
	public Object[] getCachedDatabaseSnapshot(EntityKey key) { 
		Object snapshot = entitySnapshotsByKey.get( key ); 
		if ( snapshot == NO_ROW ) { 
			throw new IllegalStateException( "persistence context reported no row snapshot for " + MessageHelper.infoString( key.getEntityName(), key.getIdentifier() ) ); 
		} 
		return ( Object[] ) snapshot; 
	} 
 
	/*public void removeDatabaseSnapshot(EntityKey key) { 
		entitySnapshotsByKey.remove(key); 
	}*/ 
 
	public void addEntity(EntityKey key, Object entity) { 
		entitiesByKey.put(key, entity); 
		getBatchFetchQueue().removeBatchLoadableEntityKey(key); 
	} 
 
	/** 
	 * Get the entity instance associated with the given 
	 * <tt>EntityKey</tt> 
	 */ 
	public Object getEntity(EntityKey key) { 
		return entitiesByKey.get(key); 
	} 
 
	public boolean containsEntity(EntityKey key) { 
		return entitiesByKey.containsKey(key); 
	} 
 
	/** 
	 * Remove an entity from the session cache, also clear 
	 * up other state associated with the entity, all except 
	 * for the <tt>EntityEntry</tt> 
	 */ 
	public Object removeEntity(EntityKey key) { 
		Object entity = entitiesByKey.remove(key); 
		Iterator iter = entitiesByUniqueKey.values().iterator(); 
		while ( iter.hasNext() ) { 
			if ( iter.next()==entity ) iter.remove(); 
		} 
		// Clear all parent cache 
		parentsByChild.clear(); 
		entitySnapshotsByKey.remove(key); 
		nullifiableEntityKeys.remove(key); 
		getBatchFetchQueue().removeBatchLoadableEntityKey(key); 
		getBatchFetchQueue().removeSubselect(key); 
		return entity; 
	} 
 
	/** 
	 * Get an entity cached by unique key 
	 */ 
	public Object getEntity(EntityUniqueKey euk) { 
		return entitiesByUniqueKey.get(euk); 
	} 
 
	/** 
	 * Add an entity to the cache by unique key 
	 */ 
	public void addEntity(EntityUniqueKey euk, Object entity) { 
		entitiesByUniqueKey.put(euk, entity); 
	} 
 
	/** 
	 * Retreive the EntityEntry representation of the given entity. 
	 * 
	 * @param entity The entity for which to locate the EntityEntry. 
	 * @return The EntityEntry for the given entity. 
	 */ 
	public EntityEntry getEntry(Object entity) { 
		return (EntityEntry) entityEntries.get(entity); 
	} 
 
	/** 
	 * Remove an entity entry from the session cache 
	 */ 
	public EntityEntry removeEntry(Object entity) { 
		return (EntityEntry) entityEntries.remove(entity); 
	} 
 
	/** 
	 * Is there an EntityEntry for this instance? 
	 */ 
	public boolean isEntryFor(Object entity) { 
		return entityEntries.containsKey(entity); 
	} 
 
	/** 
	 * Get the collection entry for a persistent collection 
	 */ 
	public CollectionEntry getCollectionEntry(PersistentCollection coll) { 
		return (CollectionEntry) collectionEntries.get(coll); 
	} 
 
	/** 
	 * Adds an entity to the internal caches. 
	 */ 
	public EntityEntry addEntity( 
			final Object entity, 
			final Status status, 
			final Object[] loadedState, 
			final EntityKey entityKey, 
			final Object version, 
			final LockMode lockMode, 
			final boolean existsInDatabase, 
			final EntityPersister persister, 
			final boolean disableVersionIncrement, 
			boolean lazyPropertiesAreUnfetched 
	) { 
 
		addEntity( entityKey, entity ); 
 
		return addEntry( 
				entity, 
				status, 
				loadedState, 
				null, 
				entityKey.getIdentifier(), 
				version, 
				lockMode, 
				existsInDatabase, 
				persister, 
				disableVersionIncrement, 
				lazyPropertiesAreUnfetched 
			); 
	} 
 
 
	/** 
	 * Generates an appropriate EntityEntry instance and adds it 
	 * to the event source's internal caches. 
	 */ 
	public EntityEntry addEntry( 
			final Object entity, 
			final Status status, 
			final Object[] loadedState, 
			final Object rowId, 
			final Serializable id, 
			final Object version, 
			final LockMode lockMode, 
			final boolean existsInDatabase, 
			final EntityPersister persister, 
			final boolean disableVersionIncrement, 
			boolean lazyPropertiesAreUnfetched) { 
 
		EntityEntry e = new EntityEntry( 
				status, 
				loadedState, 
				rowId, 
				id, 
				version, 
				lockMode, 
				existsInDatabase, 
				persister, 
				persister.getEntityMode(), 
				session.getTenantIdentifier(), 
				disableVersionIncrement, 
				lazyPropertiesAreUnfetched 
		); 
		entityEntries.put(entity, e); 
 
		setHasNonReadOnlyEnties(status); 
		return e; 
	} 
 
	public boolean containsCollection(PersistentCollection collection) { 
		return collectionEntries.containsKey(collection); 
	} 
 
	public boolean containsProxy(Object entity) { 
		return proxiesByKey.containsValue( entity ); 
	} 
 
	/** 
	 * Takes the given object and, if it represents a proxy, reassociates it with this event source. 
	 * 
	 * @param value The possible proxy to be reassociated. 
	 * @return Whether the passed value represented an actual proxy which got initialized. 
	 * @throws MappingException 
	 */ 
	public boolean reassociateIfUninitializedProxy(Object value) throws MappingException { 
		if ( value instanceof ElementWrapper ) { 
			value = ( (ElementWrapper) value ).getElement(); 
		} 
 
		if ( !Hibernate.isInitialized(value) ) { 
			HibernateProxy proxy = (HibernateProxy) value; 
			LazyInitializer li = proxy.getHibernateLazyInitializer(); 
			reassociateProxy(li, proxy); 
			return true; 
		} 
		else { 
			return false; 
		} 
	} 
 
	/** 
	 * If a deleted entity instance is re-saved, and it has a proxy, we need to 
	 * reset the identifier of the proxy 
	 */ 
	public void reassociateProxy(Object value, Serializable id) throws MappingException { 
		if ( value instanceof ElementWrapper ) { 
			value = ( (ElementWrapper) value ).getElement(); 
		} 
 
		if ( value instanceof HibernateProxy ) { 
            LOG.debugf("Setting proxy identifier: %s", id); 
			HibernateProxy proxy = (HibernateProxy) value; 
			LazyInitializer li = proxy.getHibernateLazyInitializer(); 
			li.setIdentifier(id); 
			reassociateProxy(li, proxy); 
		} 
	} 
 
	/** 
	 * Associate a proxy that was instantiated by another session with this session 
	 * 
	 * @param li The proxy initializer. 
	 * @param proxy The proxy to reassociate. 
	 */ 
	private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) { 
		if ( li.getSession() != this.getSession() ) { 
			final EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() ); 
			final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister ); 
		  	// any earlier proxy takes precedence 
			if ( !proxiesByKey.containsKey( key ) ) { 
				proxiesByKey.put( key, proxy ); 
			} 
			proxy.getHibernateLazyInitializer().setSession( session ); 
		} 
	} 
 
	/** 
	 * Get the entity instance underlying the given proxy, throwing 
	 * an exception if the proxy is uninitialized. If the given object 
	 * is not a proxy, simply return the argument. 
	 */ 
	public Object unproxy(Object maybeProxy) throws HibernateException { 
		if ( maybeProxy instanceof ElementWrapper ) { 
			maybeProxy = ( (ElementWrapper) maybeProxy ).getElement(); 
		} 
 
		if ( maybeProxy instanceof HibernateProxy ) { 
			HibernateProxy proxy = (HibernateProxy) maybeProxy; 
			LazyInitializer li = proxy.getHibernateLazyInitializer(); 
			if ( li.isUninitialized() ) { 
				throw new PersistentObjectException( 
						"object was an uninitialized proxy for " + 
						li.getEntityName() 
				); 
			} 
			return li.getImplementation(); //unwrap the object 
		} 
		else { 
			return maybeProxy; 
		} 
	} 
 
	/** 
	 * Possibly unproxy the given reference and reassociate it with the current session. 
	 * 
	 * @param maybeProxy The reference to be unproxied if it currently represents a proxy. 
	 * @return The unproxied instance. 
	 * @throws HibernateException 
	 */ 
	public Object unproxyAndReassociate(Object maybeProxy) throws HibernateException { 
		if ( maybeProxy instanceof ElementWrapper ) { 
			maybeProxy = ( (ElementWrapper) maybeProxy ).getElement(); 
		} 
 
		if ( maybeProxy instanceof HibernateProxy ) { 
			HibernateProxy proxy = (HibernateProxy) maybeProxy; 
			LazyInitializer li = proxy.getHibernateLazyInitializer(); 
			reassociateProxy(li, proxy); 
			return li.getImplementation(); //initialize + unwrap the object 
		} 
		else { 
			return maybeProxy; 
		} 
	} 
 
	/** 
	 * Attempts to check whether the given key represents an entity already loaded within the 
	 * current session. 
	 * @param object The entity reference against which to perform the uniqueness check. 
	 * @throws HibernateException 
	 */ 
	public void checkUniqueness(EntityKey key, Object object) throws HibernateException { 
		Object entity = getEntity(key); 
		if ( entity == object ) { 
			throw new AssertionFailure( "object already associated, but no entry was found" ); 
		} 
		if ( entity != null ) { 
			throw new NonUniqueObjectException( key.getIdentifier(), key.getEntityName() ); 
		} 
	} 
 
	/** 
	 * If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy 
	 * and overwrite the registration of the old one. This breaks == and occurs only for 
	 * "class" proxies rather than "interface" proxies. Also init the proxy to point to 
	 * the given target implementation if necessary. 
	 * 
	 * @param proxy The proxy instance to be narrowed. 
	 * @param persister The persister for the proxied entity. 
	 * @param key The internal cache key for the proxied entity. 
	 * @param object (optional) the actual proxied entity instance. 
	 * @return An appropriately narrowed instance. 
	 * @throws HibernateException 
	 */ 
	public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key, Object object) 
			throws HibernateException { 
 
		final Class concreteProxyClass = persister.getConcreteProxyClass(); 
		boolean alreadyNarrow = concreteProxyClass.isAssignableFrom( proxy.getClass() ); 
 
		if ( !alreadyNarrow ) { 
            if ( LOG.isEnabled(WARN) ) { 
				LOG.narrowingProxy( concreteProxyClass ); 
			} 
 
			if ( object != null ) { 
				proxiesByKey.remove(key); 
				return object; //return the proxied object 
			} 
			else { 
				proxy = persister.createProxy( key.getIdentifier(), session ); 
				Object proxyOrig = proxiesByKey.put(key, proxy); //overwrite old proxy 
				if ( proxyOrig != null ) { 
					if ( ! ( proxyOrig instanceof HibernateProxy ) ) { 
						throw new AssertionFailure( 
								"proxy not of type HibernateProxy; it is " + proxyOrig.getClass() 
						); 
					} 
					// set the read-only/modifiable mode in the new proxy to what it was in the original proxy 
					boolean readOnlyOrig = ( ( HibernateProxy ) proxyOrig ).getHibernateLazyInitializer().isReadOnly(); 
					( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().setReadOnly( readOnlyOrig ); 
				} 
				return proxy; 
			} 
		} 
		else { 
 
			if ( object != null ) { 
				LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); 
				li.setImplementation(object); 
			} 
 
			return proxy; 
 
		} 
 
	} 
 
	/** 
	 * Return the existing proxy associated with the given <tt>EntityKey</tt>, or the 
	 * third argument (the entity associated with the key) if no proxy exists. Init 
	 * the proxy to the target implementation, if necessary. 
	 */ 
	public Object proxyFor(EntityPersister persister, EntityKey key, Object impl) 
	throws HibernateException { 
		if ( !persister.hasProxy() ) return impl; 
		Object proxy = proxiesByKey.get(key); 
		if ( proxy != null ) { 
			return narrowProxy(proxy, persister, key, impl); 
		} 
		else { 
			return impl; 
		} 
	} 
 
	/** 
	 * Return the existing proxy associated with the given <tt>EntityKey</tt>, or the 
	 * argument (the entity associated with the key) if no proxy exists. 
	 * (slower than the form above) 
	 */ 
	public Object proxyFor(Object impl) throws HibernateException { 
		EntityEntry e = getEntry(impl); 
		return proxyFor( e.getPersister(), e.getEntityKey(), impl ); 
	} 
 
	/** 
	 * Get the entity that owns this persistent collection 
	 */ 
	public Object getCollectionOwner(Serializable key, CollectionPersister collectionPersister) throws MappingException { 
		return getEntity( session.generateEntityKey( key, collectionPersister.getOwnerEntityPersister() ) ); 
	} 
 
	/** 
	 * Get the entity that owned this persistent collection when it was loaded 
	 * 
	 * @param collection The persistent collection 
	 * @return the owner, if its entity ID is available from the collection's loaded key 
	 * and the owner entity is in the persistence context; otherwise, returns null 
	 */ 
	public Object getLoadedCollectionOwnerOrNull(PersistentCollection collection) { 
		CollectionEntry ce = getCollectionEntry( collection ); 
		if ( ce.getLoadedPersister() == null ) { 
			return null; // early exit... 
		} 
		Object loadedOwner = null; 
		// TODO: an alternative is to check if the owner has changed; if it hasn't then 
		// return collection.getOwner() 
		Serializable entityId = getLoadedCollectionOwnerIdOrNull( ce ); 
		if ( entityId != null ) { 
			loadedOwner = getCollectionOwner( entityId, ce.getLoadedPersister() ); 
		} 
		return loadedOwner; 
	} 
 
	/** 
	 * Get the ID for the entity that owned this persistent collection when it was loaded 
	 * 
	 * @param collection The persistent collection 
	 * @return the owner ID if available from the collection's loaded key; otherwise, returns null 
	 */ 
	public Serializable getLoadedCollectionOwnerIdOrNull(PersistentCollection collection) { 
		return getLoadedCollectionOwnerIdOrNull( getCollectionEntry( collection ) ); 
	} 
 
	/** 
	 * Get the ID for the entity that owned this persistent collection when it was loaded 
	 * 
	 * @param ce The collection entry 
	 * @return the owner ID if available from the collection's loaded key; otherwise, returns null 
	 */ 
	private Serializable getLoadedCollectionOwnerIdOrNull(CollectionEntry ce) { 
		if ( ce == null || ce.getLoadedKey() == null || ce.getLoadedPersister() == null ) { 
			return null; 
		} 
		// TODO: an alternative is to check if the owner has changed; if it hasn't then 
		// get the ID from collection.getOwner() 
		return ce.getLoadedPersister().getCollectionType().getIdOfOwnerOrNull( ce.getLoadedKey(), session ); 
	} 
 
	/** 
	 * add a collection we just loaded up (still needs initializing) 
	 */ 
	public void addUninitializedCollection(CollectionPersister persister, PersistentCollection collection, Serializable id) { 
		CollectionEntry ce = new CollectionEntry(collection, persister, id, flushing); 
		addCollection(collection, ce, id); 
	}