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

View File

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

View File

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

View File

@ -9,10 +9,11 @@ package org.hibernate.event.internal;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.Collections;
import org.hibernate.event.spi.EventSource;
import org.hibernate.type.CollectionType;
import static org.hibernate.engine.internal.Collections.processReachableCollection;
/**
* Process collections reachable from an entity. This
* 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 {
if ( collection == CollectionType.UNFETCHED_COLLECTION ) {
return null;
}
if ( collection != null ) {
else if ( collection != null ) {
final EventSource session = getSession();
final PersistentCollection<?> coll;
final PersistentCollection<?> persistentCollection;
if ( type.hasHolder() ) {
coll = session.getPersistenceContextInternal().getCollectionHolder(collection);
persistentCollection = session.getPersistenceContextInternal().getCollectionHolder( collection );
}
else if ( collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
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 ) {
coll = (PersistentCollection<?>) collection;
else if ( collection instanceof PersistentCollection<?> wrapper ) {
persistentCollection = wrapper;
}
else {
return null;
}
Collections.processReachableCollection( coll, type, owner, session );
processReachableCollection( persistentCollection, type, owner, session );
return null;
}
else {
return null;
}
return null;
}
@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
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
* existing snapshot
* 3. throw an exception for each "new" collection
* <ol>
* <li> associate any uninitialized PersistentCollections with this session
* <li> associate any initialized PersistentCollections with this session, using the
* existing snapshot
* <li> throw an exception for each "new" collection
* </ol>
*
* @author Gavin King
*/
@ -35,13 +37,10 @@ public class OnLockVisitor extends ReattachVisitor {
}
final SessionImplementor session = getSession();
final CollectionPersister persister = session.getFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
if ( collection instanceof PersistentCollection ) {
final PersistentCollection<?> persistentCollection = (PersistentCollection<?>) collection;
final CollectionPersister persister =
session.getFactory().getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
if ( collection instanceof PersistentCollection<?> persistentCollection ) {
if ( persistentCollection.setCurrentSession( session ) ) {
if ( isOwnerUnchanged( persister, extractCollectionKeyFromOwner( persister ), persistentCollection ) ) {
// 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??
throw new HibernateException( "re-associated object has dirty collection reference (or an array)" );
}
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
* inspect all its collections and
* 1. associate any uninitialized PersistentCollections with this session
* 2. associate any initialized PersistentCollections with this session, using the
* existing snapshot
* 3. execute a collection removal (SQL DELETE) for each null collection property
* or "new" collection
*
* <ol>
* <li> associate any uninitialized PersistentCollections with this session
* <li> associate any initialized PersistentCollections with this session, using the
* existing snapshot
* <li> execute a collection removal (SQL DELETE) for each null collection property
* or "new" collection
*</ol>
* @author Gavin King
*/
public class OnReplicateVisitor extends ReattachVisitor {
@ -39,33 +40,28 @@ public class OnReplicateVisitor extends ReattachVisitor {
}
final EventSource session = getSession();
final CollectionPersister persister = session.getFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
final CollectionPersister persister =
session.getFactory().getMappingMetamodel()
.getCollectionDescriptor( type.getRole() );
if ( isUpdate ) {
removeCollection( persister, extractCollectionKeyFromOwner( persister ), session );
}
if ( collection instanceof PersistentCollection ) {
final PersistentCollection<?> wrapper = (PersistentCollection<?>) collection;
wrapper.setCurrentSession( session );
if ( wrapper.wasInitialized() ) {
session.getPersistenceContextInternal().addNewCollection( persister, wrapper );
if ( collection instanceof PersistentCollection<?> persistentCollection ) {
persistentCollection.setCurrentSession( session );
if ( persistentCollection.wasInitialized() ) {
session.getPersistenceContextInternal().addNewCollection( persister, persistentCollection );
}
else {
reattachCollection( wrapper, type );
reattachCollection( persistentCollection, type );
}
}
// else {
// otherwise a null or brand new collection
// otherwise a null or brand-new collection
// this will also (inefficiently) handle arrays, which
// have no snapshot, so we can't do any better
//processArrayOrNewCollection(collection, type);
// }
return null;
}
}

View File

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

View File

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

View File

@ -13,6 +13,7 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
@ -56,7 +57,7 @@ public abstract class ReattachVisitor extends ProxyVisitor {
*/
@Override
Object processComponent(Object component, CompositeType componentType) throws HibernateException {
Type[] types = componentType.getSubtypes();
final Type[] types = componentType.getSubtypes();
if ( component == null ) {
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
*/
final Object extractCollectionKeyFromOwner(CollectionPersister role) {
if ( role.getCollectionType().useLHSPrimaryKey() ) {
final CollectionType collectionType = role.getCollectionType();
if ( collectionType.useLHSPrimaryKey() ) {
return ownerIdentifier;
}
return role.getOwnerEntityPersister().getPropertyValue(
owner,
role.getCollectionType().getLHSPropertyName()
);
return role.getOwnerEntityPersister()
.getPropertyValue( owner, collectionType.getLHSPropertyName() );
}
}

View File

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