code cleanup in Visitors

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-09-02 10:41:44 +02:00
parent 763401a5c8
commit f6ff6fa0f7
10 changed files with 130 additions and 188 deletions

View File

@ -74,11 +74,8 @@ public abstract class AbstractVisitor {
* to processValue(). * to processValue().
*/ */
Object processComponent(Object component, CompositeType componentType) throws HibernateException { Object processComponent(Object component, CompositeType componentType) throws HibernateException {
if (component!=null) { if ( component!=null ) {
processValues( processValues( componentType.getPropertyValues(component, session), componentType.getSubtypes() );
componentType.getPropertyValues(component, session),
componentType.getSubtypes()
);
} }
return null; return null;
} }
@ -88,19 +85,18 @@ public abstract class AbstractVisitor {
* correct handler for the property type. * correct handler for the property type.
*/ */
final Object processValue(Object value, Type type) throws HibernateException { final Object processValue(Object value, Type type) throws HibernateException {
if ( type instanceof CollectionType collectionType ) {
if ( type instanceof CollectionType ) {
//even process null collections //even process null collections
return processCollection( value, (CollectionType) type ); return processCollection( value, collectionType );
} }
else if ( type instanceof EntityType ) { else if ( type instanceof EntityType entityType ) {
return processEntity( value, (EntityType) type ); return processEntity( value, entityType );
} }
else if ( type instanceof ComponentType ) { else if ( type instanceof ComponentType componentType ) {
return processComponent( value, (ComponentType) type ); return processComponent( value, componentType );
} }
else if ( type instanceof AnyType ) { else if ( type instanceof AnyType anyType ) {
return processComponent( value, (AnyType) type ); return processComponent( value, anyType );
} }
else { else {
return null; return null;
@ -111,20 +107,15 @@ public abstract class AbstractVisitor {
* Walk the tree starting from the given entity. * Walk the tree starting from the given entity.
* *
*/ */
public void process(Object object, EntityPersister persister) public void process(Object object, EntityPersister persister) throws HibernateException {
throws HibernateException { processEntityPropertyValues( persister.getValues( object ), persister.getPropertyTypes() );
processEntityPropertyValues(
persister.getValues( object ),
persister.getPropertyTypes()
);
} }
/** /**
* Visit a collection. Default superclass * Visit a collection. Default superclass
* implementation is a no-op. * implementation is a no-op.
*/ */
Object processCollection(Object collection, CollectionType type) Object processCollection(Object collection, CollectionType type) throws HibernateException {
throws HibernateException {
return null; return null;
} }
@ -133,8 +124,7 @@ public abstract class AbstractVisitor {
* entity. Default superclass implementation is * entity. Default superclass implementation is
* a no-op. * a no-op.
*/ */
Object processEntity(Object value, EntityType entityType) Object processEntity(Object value, EntityType entityType) throws HibernateException {
throws HibernateException {
return null; return null;
} }

View File

@ -37,7 +37,8 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor {
super( session ); super( session );
EnhancementAsProxyLazinessInterceptor interceptor = null; EnhancementAsProxyLazinessInterceptor interceptor = null;
if ( isPersistentAttributeInterceptable( entity ) ) { if ( isPersistentAttributeInterceptable( entity ) ) {
PersistentAttributeInterceptor attributeInterceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor(); PersistentAttributeInterceptor attributeInterceptor =
asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
if ( attributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) { if ( attributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
interceptor = (EnhancementAsProxyLazinessInterceptor) attributeInterceptor; interceptor = (EnhancementAsProxyLazinessInterceptor) attributeInterceptor;
} }
@ -53,31 +54,25 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor {
Object processCollection(Object collection, CollectionType type) throws HibernateException { Object processCollection(Object collection, CollectionType type) throws HibernateException {
if ( collection != null ) { if ( collection != null ) {
final SessionImplementor session = getSession(); final SessionImplementor session = getSession();
final PersistentCollection<?> persistentCollection;
if ( type.isArrayType() ) { if ( type.isArrayType() ) {
persistentCollection = session.getPersistenceContextInternal().getCollectionHolder( collection ); // if no array holder we found an unwrapped array, it's dirty
// if no array holder we found an unwrapped array (this can't occur, // (this can't occur, because we now always call wrap() before getting to here)
// because we now always call wrap() before getting to here)
// return (ah==null) ? true : searchForDirtyCollections(ah, type);
}
else {
if ( interceptor != null && !interceptor.isAttributeLoaded( type.getName() ) ) {
return null; //NOTE: EARLY EXIT!
}
else {
// if not wrapped yet, it's dirty
// (this can't occur, because we now always call wrap() before getting here)
// return ( ! (obj instanceof PersistentCollection) )
// ? true : searchForDirtyCollections( (PersistentCollection) obj, type );
persistentCollection = (PersistentCollection<?>) collection;
}
}
if ( persistentCollection.isDirty() ) { //we need to check even if it was not initialized, because of delayed adds! // we need to check even if it was not initialized, because of delayed adds!
dirty = true; if ( session.getPersistenceContextInternal().getCollectionHolder( collection ).isDirty() ) {
dirty = true;
}
}
else if ( interceptor == null || interceptor.isAttributeLoaded( type.getName() ) ) {
// if not wrapped yet, it's dirty
// (this can't occur, because we now always call wrap() before getting here)
// we need to check even if it was not initialized, because of delayed adds!
if ( ((PersistentCollection<?>) collection).isDirty() ) {
dirty = true;
}
} }
} }
return null; return null;
} }

View File

@ -42,22 +42,21 @@ public class EvictVisitor extends AbstractVisitor {
if ( collection != null ) { if ( collection != null ) {
evictCollection( collection, type ); evictCollection( collection, type );
} }
return null; return null;
} }
public void evictCollection(Object value, CollectionType type) { public void evictCollection(Object value, CollectionType type) {
final PersistentCollection<?> collection;
final EventSource session = getSession(); final EventSource session = getSession();
final PersistentCollection<?> collection;
if ( type.hasHolder() ) { if ( type.hasHolder() ) {
collection = session.getPersistenceContextInternal().removeCollectionHolder(value); collection = session.getPersistenceContextInternal().removeCollectionHolder( value );
} }
else if ( value instanceof PersistentCollection ) { else if ( value instanceof PersistentCollection<?> persistentCollection ) {
collection = (PersistentCollection<?>) value; collection = persistentCollection;
} }
else if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { else if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
final Object keyOfOwner = type.getKeyOfOwner( owner, session ); collection = (PersistentCollection<?>)
collection = (PersistentCollection<?>) type.getCollection( keyOfOwner, session, owner, false ); type.getCollection( type.getKeyOfOwner( owner, session ), session, owner, false );
} }
else { else {
return; //EARLY EXIT! return; //EARLY EXIT!

View File

@ -9,10 +9,11 @@ package org.hibernate.event.internal;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.Collections;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import static org.hibernate.engine.internal.Collections.processReachableCollection;
/** /**
* Process collections reachable from an entity. This * Process collections reachable from an entity. This
* visitor assumes that wrap was already performed for * visitor assumes that wrap was already performed for
@ -29,33 +30,32 @@ public class FlushVisitor extends AbstractVisitor {
} }
Object processCollection(Object collection, CollectionType type) throws HibernateException { Object processCollection(Object collection, CollectionType type) throws HibernateException {
if ( collection == CollectionType.UNFETCHED_COLLECTION ) { if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
return null; return null;
} }
else if ( collection != null ) {
if ( collection != null ) {
final EventSource session = getSession(); final EventSource session = getSession();
final PersistentCollection<?> coll; final PersistentCollection<?> persistentCollection;
if ( type.hasHolder() ) { if ( type.hasHolder() ) {
coll = session.getPersistenceContextInternal().getCollectionHolder(collection); persistentCollection = session.getPersistenceContextInternal().getCollectionHolder( collection );
} }
else if ( collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { else if ( collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
final Object keyOfOwner = type.getKeyOfOwner( owner, session ); final Object keyOfOwner = type.getKeyOfOwner( owner, session );
coll = (PersistentCollection<?>) type.getCollection( keyOfOwner, session, owner, Boolean.FALSE ); persistentCollection = (PersistentCollection<?>)
type.getCollection( keyOfOwner, session, owner, Boolean.FALSE );
} }
else if ( collection instanceof PersistentCollection ) { else if ( collection instanceof PersistentCollection<?> wrapper ) {
coll = (PersistentCollection<?>) collection; persistentCollection = wrapper;
} }
else { else {
return null; return null;
} }
processReachableCollection( persistentCollection, type, owner, session );
Collections.processReachableCollection( coll, type, owner, session ); return null;
}
else {
return null;
} }
return null;
} }
@Override @Override

View File

@ -15,10 +15,12 @@ import org.hibernate.type.CollectionType;
/** /**
* When a transient entity is passed to lock(), we must inspect all its collections and * When a transient entity is passed to lock(), we must inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session * <ol>
* 2. associate any initialized PersistentCollections with this session, using the * <li> associate any uninitialized PersistentCollections with this session
* existing snapshot * <li> associate any initialized PersistentCollections with this session, using the
* 3. throw an exception for each "new" collection * existing snapshot
* <li> throw an exception for each "new" collection
* </ol>
* *
* @author Gavin King * @author Gavin King
*/ */
@ -35,13 +37,10 @@ public class OnLockVisitor extends ReattachVisitor {
} }
final SessionImplementor session = getSession(); final SessionImplementor session = getSession();
final CollectionPersister persister = session.getFactory() final CollectionPersister persister =
.getRuntimeMetamodels() session.getFactory().getMappingMetamodel()
.getMappingMetamodel() .getCollectionDescriptor( type.getRole() );
.getCollectionDescriptor( type.getRole() ); if ( collection instanceof PersistentCollection<?> persistentCollection ) {
if ( collection instanceof PersistentCollection ) {
final PersistentCollection<?> persistentCollection = (PersistentCollection<?>) collection;
if ( persistentCollection.setCurrentSession( session ) ) { if ( persistentCollection.setCurrentSession( session ) ) {
if ( isOwnerUnchanged( persister, extractCollectionKeyFromOwner( persister ), persistentCollection ) ) { if ( isOwnerUnchanged( persister, extractCollectionKeyFromOwner( persister ), persistentCollection ) ) {
// a "detached" collection that originally belonged to the same entity // a "detached" collection that originally belonged to the same entity
@ -67,7 +66,6 @@ public class OnLockVisitor extends ReattachVisitor {
//TODO: or an array!! we can't lock objects with arrays now?? //TODO: or an array!! we can't lock objects with arrays now??
throw new HibernateException( "re-associated object has dirty collection reference (or an array)" ); throw new HibernateException( "re-associated object has dirty collection reference (or an array)" );
} }
return null; return null;
} }

View File

@ -15,12 +15,13 @@ import org.hibernate.type.CollectionType;
/** /**
* When an entity is passed to replicate(), and there is an existing row, we must * When an entity is passed to replicate(), and there is an existing row, we must
* inspect all its collections and * inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session * <ol>
* 2. associate any initialized PersistentCollections with this session, using the * <li> associate any uninitialized PersistentCollections with this session
* existing snapshot * <li> associate any initialized PersistentCollections with this session, using the
* 3. execute a collection removal (SQL DELETE) for each null collection property * existing snapshot
* or "new" collection * <li> execute a collection removal (SQL DELETE) for each null collection property
* * or "new" collection
*</ol>
* @author Gavin King * @author Gavin King
*/ */
public class OnReplicateVisitor extends ReattachVisitor { public class OnReplicateVisitor extends ReattachVisitor {
@ -39,33 +40,28 @@ public class OnReplicateVisitor extends ReattachVisitor {
} }
final EventSource session = getSession(); final EventSource session = getSession();
final CollectionPersister persister = session.getFactory() final CollectionPersister persister =
.getRuntimeMetamodels() session.getFactory().getMappingMetamodel()
.getMappingMetamodel() .getCollectionDescriptor( type.getRole() );
.getCollectionDescriptor( type.getRole() );
if ( isUpdate ) { if ( isUpdate ) {
removeCollection( persister, extractCollectionKeyFromOwner( persister ), session ); removeCollection( persister, extractCollectionKeyFromOwner( persister ), session );
} }
if ( collection instanceof PersistentCollection ) { if ( collection instanceof PersistentCollection<?> persistentCollection ) {
final PersistentCollection<?> wrapper = (PersistentCollection<?>) collection; persistentCollection.setCurrentSession( session );
wrapper.setCurrentSession( session ); if ( persistentCollection.wasInitialized() ) {
if ( wrapper.wasInitialized() ) { session.getPersistenceContextInternal().addNewCollection( persister, persistentCollection );
session.getPersistenceContextInternal().addNewCollection( persister, wrapper );
} }
else { else {
reattachCollection( wrapper, type ); reattachCollection( persistentCollection, type );
} }
} }
// else { // else {
// otherwise a null or brand new collection // otherwise a null or brand-new collection
// this will also (inefficiently) handle arrays, which // this will also (inefficiently) handle arrays, which
// have no snapshot, so we can't do any better // have no snapshot, so we can't do any better
//processArrayOrNewCollection(collection, type); //processArrayOrNewCollection(collection, type);
// } // }
return null; return null;
} }
} }

View File

@ -30,42 +30,37 @@ public class OnUpdateVisitor extends ReattachVisitor {
@Override @Override
Object processCollection(Object collection, CollectionType type) throws HibernateException { Object processCollection(Object collection, CollectionType type) throws HibernateException {
if ( collection == CollectionType.UNFETCHED_COLLECTION ) { if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
return null; return null;
} }
final EventSource session = getSession(); final EventSource session = getSession();
final CollectionPersister persister =
final CollectionPersister persister = session.getFactory() session.getFactory().getMappingMetamodel()
.getRuntimeMetamodels() .getCollectionDescriptor( type.getRole() );
.getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
final Object collectionKey = extractCollectionKeyFromOwner( persister ); final Object collectionKey = extractCollectionKeyFromOwner( persister );
if ( ( collection instanceof PersistentCollection ) ) { if ( collection instanceof PersistentCollection<?> persistentCollection ) {
PersistentCollection<?> wrapper = (PersistentCollection<?>) collection; if ( persistentCollection.setCurrentSession( session ) ) {
if ( wrapper.setCurrentSession(session) ) {
//a "detached" collection! //a "detached" collection!
if ( !isOwnerUnchanged( persister, collectionKey, wrapper ) ) { if ( !isOwnerUnchanged( persister, collectionKey, persistentCollection ) ) {
// if the collection belonged to a different entity, // if the collection belonged to a different entity,
// clean up the existing state of the collection // clean up the existing state of the collection
removeCollection( persister, collectionKey, session ); removeCollection( persister, collectionKey, session );
} }
reattachCollection(wrapper, type); reattachCollection( persistentCollection, type );
} }
else { else {
// a collection loaded in the current session // a collection loaded in the current session
// can not possibly be the collection belonging // can not possibly be the collection belonging
// to the entity passed to update() // to the entity passed to update()
removeCollection(persister, collectionKey, session); removeCollection( persister, collectionKey, session );
} }
} }
else { else {
// null or brand-new collection // null or brand-new collection
// this will also (inefficiently) handle arrays, which have // this will also (inefficiently) handle arrays, which have
// no snapshot, so we can't do any better // no snapshot, so we can't do any better
removeCollection(persister, collectionKey, session); removeCollection( persister, collectionKey, session );
} }
return null; return null;

View File

@ -9,6 +9,7 @@ package org.hibernate.event.internal;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
@ -23,14 +24,12 @@ public abstract class ProxyVisitor extends AbstractVisitor {
super(session); super(session);
} }
Object processEntity(Object value, EntityType entityType) throws HibernateException { Object processEntity(Object value, EntityType entityType) {
if ( value != null ) { if ( value != null ) {
getSession().getPersistenceContext().reassociateIfUninitializedProxy(value); getSession().getPersistenceContext().reassociateIfUninitializedProxy( value );
// if it is an initialized proxy, let cascade // if it is an initialized proxy, let cascade
// handle it later on // handle it later on
} }
return null; return null;
} }
@ -39,11 +38,8 @@ public abstract class ProxyVisitor extends AbstractVisitor {
* was snapshotted and detached? * was snapshotted and detached?
*/ */
protected static boolean isOwnerUnchanged( protected static boolean isOwnerUnchanged(
final CollectionPersister persister, CollectionPersister persister, Object id, PersistentCollection<?> snapshot) {
final Object id, return isCollectionSnapshotValid( snapshot )
final PersistentCollection<?> snapshot
) {
return isCollectionSnapshotValid(snapshot)
&& persister.getRole().equals( snapshot.getRole() ) && persister.getRole().equals( snapshot.getRole() )
&& id.equals( snapshot.getKey() ); && id.equals( snapshot.getKey() );
} }
@ -62,21 +58,16 @@ public abstract class ProxyVisitor extends AbstractVisitor {
protected void reattachCollection(PersistentCollection<?> collection, CollectionType type) protected void reattachCollection(PersistentCollection<?> collection, CollectionType type)
throws HibernateException { throws HibernateException {
final EventSource session = getSession(); final EventSource session = getSession();
final MappingMetamodelImplementor metamodel = session.getFactory().getMappingMetamodel();
if ( collection.wasInitialized() ) { if ( collection.wasInitialized() ) {
final CollectionPersister persister = session.getFactory() final CollectionPersister persister = metamodel.getCollectionDescriptor( type.getRole() );
.getRuntimeMetamodels()
.getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
session.getPersistenceContext().addInitializedDetachedCollection( persister, collection ); session.getPersistenceContext().addInitializedDetachedCollection( persister, collection );
} }
else { else {
if ( !isCollectionSnapshotValid( collection ) ) { if ( !isCollectionSnapshotValid( collection ) ) {
throw new HibernateException( "could not re-associate uninitialized transient collection" ); throw new HibernateException( "could not re-associate uninitialized transient collection" );
} }
final CollectionPersister persister = session.getFactory() final CollectionPersister persister = metamodel.getCollectionDescriptor( collection.getRole() );
.getRuntimeMetamodels()
.getMappingMetamodel()
.getCollectionDescriptor( collection.getRole() );
session.getPersistenceContext().addUninitializedDetachedCollection( persister, collection ); session.getPersistenceContext().addUninitializedDetachedCollection( persister, collection );
} }
} }

View File

@ -13,6 +13,7 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -56,7 +57,7 @@ public abstract class ReattachVisitor extends ProxyVisitor {
*/ */
@Override @Override
Object processComponent(Object component, CompositeType componentType) throws HibernateException { Object processComponent(Object component, CompositeType componentType) throws HibernateException {
Type[] types = componentType.getSubtypes(); final Type[] types = componentType.getSubtypes();
if ( component == null ) { if ( component == null ) {
processValues( new Object[types.length], types ); processValues( new Object[types.length], types );
} }
@ -97,12 +98,11 @@ public abstract class ReattachVisitor extends ProxyVisitor {
* @return The value from the owner that identifies the grouping into the collection * @return The value from the owner that identifies the grouping into the collection
*/ */
final Object extractCollectionKeyFromOwner(CollectionPersister role) { final Object extractCollectionKeyFromOwner(CollectionPersister role) {
if ( role.getCollectionType().useLHSPrimaryKey() ) { final CollectionType collectionType = role.getCollectionType();
if ( collectionType.useLHSPrimaryKey() ) {
return ownerIdentifier; return ownerIdentifier;
} }
return role.getOwnerEntityPersister().getPropertyValue( return role.getOwnerEntityPersister()
owner, .getPropertyValue( owner, collectionType.getLHSPropertyName() );
role.getCollectionType().getLHSPropertyName()
);
} }
} }

View File

@ -20,9 +20,7 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -30,6 +28,7 @@ import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.persister.entity.AbstractEntityPersister.getCollectionKey;
/** /**
* Wrap collections in a Hibernate collection wrapper. * Wrap collections in a Hibernate collection wrapper.
@ -56,84 +55,65 @@ public class WrapVisitor extends ProxyVisitor {
@Override @Override
protected Object processCollection(Object collection, CollectionType collectionType) protected Object processCollection(Object collection, CollectionType collectionType)
throws HibernateException { throws HibernateException {
if ( collection == null || collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { if ( collection == null || collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
return null; return null;
} }
else if ( collection instanceof PersistentCollection<?> persistentCollection ) {
if ( collection instanceof PersistentCollection ) { if ( persistentCollection.setCurrentSession( getSession() ) ) {
final PersistentCollection<?> coll = (PersistentCollection<?>) collection; reattachCollection( persistentCollection, collectionType );
if ( coll.setCurrentSession( getSession() ) ) {
reattachCollection( coll, collectionType );
} }
return null; return null;
} }
else {
return processArrayOrNewCollection( collection, collectionType ); return processArrayOrNewCollection( collection, collectionType );
}
} }
final Object processArrayOrNewCollection(Object collection, CollectionType collectionType) final Object processArrayOrNewCollection(Object collection, CollectionType collectionType)
throws HibernateException { throws HibernateException {
final SessionImplementor session = getSession();
if ( collection == null ) { if ( collection == null ) {
//do nothing //do nothing
return null; return null;
} }
else { else {
final MappingMetamodelImplementor mappingMetamodel = session.getFactory() final SessionImplementor session = getSession();
.getRuntimeMetamodels() final CollectionPersister persister =
.getMappingMetamodel(); session.getFactory().getMappingMetamodel()
final CollectionPersister persister = mappingMetamodel.getCollectionDescriptor( collectionType.getRole() ); .getCollectionDescriptor( collectionType.getRole() );
final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
//TODO: move into collection type, so we can use polymorphism! //TODO: move into collection type, so we can use polymorphism!
if ( collectionType.hasHolder() ) { if ( collectionType.hasHolder() ) {
if ( collection != CollectionType.UNFETCHED_COLLECTION ) {
if ( collection == CollectionType.UNFETCHED_COLLECTION ) { if ( persistenceContext.getCollectionHolder( collection ) == null ) {
return null; final PersistentCollection<?> collectionHolder = collectionType.wrap( session, collection );
} persistenceContext.addNewCollection( persister, collectionHolder );
persistenceContext.addCollectionHolder( collectionHolder );
PersistentCollection<?> ah = persistenceContext.getCollectionHolder( collection ); }
if ( ah == null ) {
ah = collectionType.wrap( session, collection );
persistenceContext.addNewCollection( persister, ah );
persistenceContext.addCollectionHolder( ah );
} }
return null; return null;
} }
else { else {
if ( isPersistentAttributeInterceptable( entity ) ) { if ( isPersistentAttributeInterceptable( entity ) ) {
PersistentAttributeInterceptor attributeInterceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor(); final PersistentAttributeInterceptor attributeInterceptor =
asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
if ( attributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) { if ( attributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
return null; return null;
} }
else if ( attributeInterceptor != null else if ( attributeInterceptor != null
&& ((LazyAttributeLoadingInterceptor)attributeInterceptor).isAttributeLoaded( persister.getAttributeMapping().getAttributeName() ) ) { && ((LazyAttributeLoadingInterceptor) attributeInterceptor)
.isAttributeLoaded( persister.getAttributeMapping().getAttributeName() ) ) {
final EntityEntry entry = persistenceContext.getEntry( entity ); final EntityEntry entry = persistenceContext.getEntry( entity );
if ( entry.isExistsInDatabase() ) { if ( entry.isExistsInDatabase() ) {
final Object key = AbstractEntityPersister.getCollectionKey( final Object key = getCollectionKey( persister, entity, entry, session );
persister,
entity,
entry,
session
);
if ( key != null ) { if ( key != null ) {
PersistentCollection<?> collectionInstance = persistenceContext.getCollection( PersistentCollection<?> collectionInstance =
new CollectionKey( persister, key ) persistenceContext.getCollection( new CollectionKey( persister, key ) );
);
if ( collectionInstance == null ) { if ( collectionInstance == null ) {
// the collection has not been initialized and new collection values have been assigned, // the collection has not been initialized and new collection values have been assigned,
// we need to be sure to delete all the collection elements before inserting the new ones // we need to be sure to delete all the collection elements before inserting the new ones
collectionInstance = persister.getCollectionSemantics().instantiateWrapper( collectionInstance =
key, persister.getCollectionSemantics()
persister, .instantiateWrapper( key, persister, session );
session
);
persistenceContext.addUninitializedCollection( persister, collectionInstance, key ); persistenceContext.addUninitializedCollection( persister, collectionInstance, key );
final CollectionEntry collectionEntry = final CollectionEntry collectionEntry =
persistenceContext.getCollectionEntry( collectionInstance ); persistenceContext.getCollectionEntry( collectionInstance );
@ -146,11 +126,9 @@ public class WrapVisitor extends ProxyVisitor {
final PersistentCollection<?> persistentCollection = collectionType.wrap( session, collection ); final PersistentCollection<?> persistentCollection = collectionType.wrap( session, collection );
persistenceContext.addNewCollection( persister, persistentCollection ); persistenceContext.addNewCollection( persister, persistentCollection );
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Wrapped collection in role: {0}", collectionType.getRole() ); LOG.tracev( "Wrapped collection in role: {0}", collectionType.getRole() );
} }
return persistentCollection; //Force a substitution! return persistentCollection; //Force a substitution!
} }
} }
@ -158,7 +136,7 @@ public class WrapVisitor extends ProxyVisitor {
@Override @Override
protected void processValue(int i, Object[] values, Type[] types) { protected void processValue(int i, Object[] values, Type[] types) {
Object result = processValue( values[i], types[i] ); final Object result = processValue( values[i], types[i] );
if ( result != null ) { if ( result != null ) {
substitute = true; substitute = true;
values[i] = result; values[i] = result;
@ -168,8 +146,8 @@ public class WrapVisitor extends ProxyVisitor {
@Override @Override
protected Object processComponent(Object component, CompositeType componentType) throws HibernateException { protected Object processComponent(Object component, CompositeType componentType) throws HibernateException {
if ( component != null ) { if ( component != null ) {
Object[] values = componentType.getPropertyValues( component, getSession() ); final Object[] values = componentType.getPropertyValues( component, getSession() );
Type[] types = componentType.getSubtypes(); final Type[] types = componentType.getSubtypes();
boolean substituteComponent = false; boolean substituteComponent = false;
for ( int i = 0; i < types.length; i++ ) { for ( int i = 0; i < types.length; i++ ) {
Object result = processValue( values[i], types[i] ); Object result = processValue( values[i], types[i] );