From 47024e7bd5f1831174969a5edb1c468f236eb425 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 22 Jul 2023 11:47:29 +0200 Subject: [PATCH] miscellaneous code cleanups --- .../org/hibernate/engine/spi/ActionQueue.java | 174 ++++++++--------- .../sqm/internal/SqmCriteriaNodeBuilder.java | 21 +- .../java/org/hibernate/type/AbstractType.java | 65 +++---- .../org/hibernate/type/ComponentType.java | 179 ++++++++---------- 4 files changed, 199 insertions(+), 240 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java index ae95f4705b..2522897576 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java @@ -50,20 +50,20 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.internal.EntityCollectionPart; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.type.CollectionType; import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; import org.hibernate.type.ForeignKeyDirection; -import org.hibernate.type.OneToOneType; import org.hibernate.type.Type; +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; + /** * Responsible for maintaining the queue of actions related to events. - * - * The ActionQueue holds the DML operations queued as part of a session's transactional-write-behind semantics. The - * DML operations are queued here until a flush forces them to be executed against the database. + *

+ * The {@code ActionQueue} holds the DML operations queued as part of a session's transactional-write-behind semantics. + * The DML operations are queued here until a flush forces them to be executed against the database. * * @author Steve Ebersole * @author Gail Badner @@ -76,12 +76,11 @@ public class ActionQueue { private UnresolvedEntityInsertActions unresolvedInsertions; - // NOTE: ExecutableList fields must be instantiated via ListProvider#init or #getOrInit - // to ensure that they are instantiated consistently. + // NOTE: ExecutableList fields must be instantiated via ListProvider#init + // or #getOrInit to ensure that they are instantiated consistently. // Object insertions, updates, and deletions have list semantics because - // they must happen in the right order so as to respect referential - // integrity + // they must happen in the right order to respect referential integrity private ExecutableList insertions; private ExecutableList deletions; private ExecutableList updates; @@ -96,8 +95,8 @@ public class ActionQueue { private ExecutableList collectionRemovals; private ExecutableList orphanCollectionRemovals; - // TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. This should be removed once action/task - // ordering is improved. + // TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. + // This should be removed once action/task ordering is improved. private ExecutableList orphanRemovals; @@ -105,11 +104,11 @@ public class ActionQueue { private AfterTransactionCompletionProcessQueue afterTransactionProcesses; private BeforeTransactionCompletionProcessQueue beforeTransactionProcesses; - //Extract this as a constant to perform efficient iterations: - //method values() otherwise allocates a new array on each invocation. + // Extract this as a constant to perform efficient iterations: + // method values() otherwise allocates a new array on each invocation. private static final OrderedActions[] ORDERED_OPERATIONS = OrderedActions.values(); - //The order of these operations is very important + // The order of these operations is very important private enum OrderedActions { OrphanCollectionRemoveAction { @Override @@ -266,7 +265,7 @@ private void addInsertAction(AbstractEntityInsertAction insert) { LOG.tracev( "Executing inserts before finding non-nullable transient entities for early insert: [{0}]", insert ); executeInserts(); } - NonNullableTransientDependencies nonNullableTransientDependencies = insert.findNonNullableTransientEntities(); + final NonNullableTransientDependencies nonNullableTransientDependencies = insert.findNonNullableTransientEntities(); if ( nonNullableTransientDependencies == null ) { LOG.tracev( "Adding insert with no non-nullable, transient entities: [{0}]", insert ); addResolvedEntityInsertAction( insert ); @@ -293,13 +292,13 @@ private void addResolvedEntityInsertAction(AbstractEntityInsertAction insert) { else { LOG.trace( "Adding resolved non-early insert action." ); OrderedActions.EntityInsertAction.ensureInitialized( this ); - this.insertions.add( insert ); + insertions.add( insert ); } if ( !insert.isVeto() ) { insert.makeEntityManaged(); - if ( unresolvedInsertions != null ) { - for ( AbstractEntityInsertAction resolvedAction : unresolvedInsertions.resolveDependentActions( insert.getInstance(), session ) ) { + for ( AbstractEntityInsertAction resolvedAction : + unresolvedInsertions.resolveDependentActions( insert.getInstance(), session ) ) { addResolvedEntityInsertAction( resolvedAction ); } } @@ -329,7 +328,7 @@ public void addAction(EntityIdentityInsertAction action) { */ public void addAction(EntityDeleteAction action) { OrderedActions.EntityDeleteAction.ensureInitialized( this ); - this.deletions.add( action ); + deletions.add( action ); } /** @@ -339,7 +338,7 @@ public void addAction(EntityDeleteAction action) { */ public void addAction(final OrphanRemovalAction action) { OrderedActions.OrphanRemovalAction.ensureInitialized( this ); - this.orphanRemovals.add( action ); + orphanRemovals.add( action ); } /** @@ -349,7 +348,7 @@ public void addAction(final OrphanRemovalAction action) { */ public void addAction(final EntityUpdateAction action) { OrderedActions.EntityUpdateAction.ensureInitialized( this ); - this.updates.add( action ); + updates.add( action ); } /** @@ -359,7 +358,7 @@ public void addAction(final EntityUpdateAction action) { */ public void addAction(final CollectionRecreateAction action) { OrderedActions.CollectionRecreateAction.ensureInitialized( this ); - this.collectionCreations.add( action ); + collectionCreations.add( action ); } /** @@ -368,22 +367,23 @@ public void addAction(final CollectionRecreateAction action) { * @param action The action representing the removal of a collection */ public void addAction(final CollectionRemoveAction action) { - if ( orphanRemovals != null && action.getAffectedOwner() != null && session.getPersistenceContextInternal() - .getEntry( action.getAffectedOwner() ) - .getStatus() - .isDeletedOrGone() ) { + if ( orphanRemovals != null && action.getAffectedOwner() != null + && session.getPersistenceContextInternal() + .getEntry( action.getAffectedOwner() ) + .getStatus() + .isDeletedOrGone() ) { // We need to check if this collection's owner is an orphan being removed, // which case we should remove the collection first to avoid constraint violations for ( OrphanRemovalAction orphanRemoval : orphanRemovals ) { if ( orphanRemoval.getInstance() == action.getAffectedOwner() ) { OrderedActions.OrphanCollectionRemoveAction.ensureInitialized( this ); - this.orphanCollectionRemovals.add( action ); + orphanCollectionRemovals.add( action ); return; } } } OrderedActions.CollectionRemoveAction.ensureInitialized( this ); - this.collectionRemovals.add( action ); + collectionRemovals.add( action ); } /** @@ -393,7 +393,7 @@ public void addAction(final CollectionRemoveAction action) { */ public void addAction(final CollectionUpdateAction action) { OrderedActions.CollectionUpdateAction.ensureInitialized( this ); - this.collectionUpdates.add( action ); + collectionUpdates.add( action ); } /** @@ -423,7 +423,7 @@ private void registerCleanupActions(Executable executable) { beforeTransactionProcesses.register( executable.getBeforeTransactionCompletionProcess() ); } if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) { - invalidateSpaces( convertTimestampSpaces( executable.getPropertySpaces() ) ); + invalidateSpaces( (String[]) executable.getPropertySpaces() ); } if ( executable.getAfterTransactionCompletionProcess() != null ) { if ( afterTransactionProcesses == null ) { @@ -433,10 +433,6 @@ private void registerCleanupActions(Executable executable) { } } - private static String[] convertTimestampSpaces(Serializable[] spaces) { - return (String[]) spaces; - } - /** * Are there unresolved entity insert actions that depend on non-nullable associations with a transient entity? * @@ -653,8 +649,7 @@ private void executeActions(ExecutableList l // Strictly speaking, only a subset of the list may have been processed if a RuntimeException occurs. // We still invalidate all spaces. I don't see this as a big deal - after all, RuntimeExceptions are // unexpected. - Set propertySpaces = list.getQuerySpaces(); - invalidateSpaces( convertTimestampSpaces( propertySpaces ) ); + invalidateSpaces( list.getQuerySpaces().toArray(StringHelper.EMPTY_STRINGS) ); } } @@ -662,10 +657,6 @@ private void executeActions(ExecutableList l session.getJdbcCoordinator().executeBatch(); } - private static String[] convertTimestampSpaces(Set spaces) { - return spaces.toArray(StringHelper.EMPTY_STRINGS); - } - /** * @param executable The action to execute */ @@ -683,7 +674,7 @@ public > void execute(E executable) { * * @param spaces The spaces to invalidate */ - private void invalidateSpaces(String... spaces) { + private void invalidateSpaces(String[] spaces) { if ( spaces != null && spaces.length > 0 ) { for ( String space : spaces ) { if ( afterTransactionProcesses == null ) { @@ -855,10 +846,18 @@ public boolean hasBeforeTransactionActions() { } public boolean hasAnyQueuedActions() { - return ( updates != null && !updates.isEmpty() ) || ( insertions != null && !insertions.isEmpty() ) || hasUnresolvedEntityInsertActions() - || ( deletions != null && !deletions.isEmpty()) || ( collectionUpdates != null && !collectionUpdates.isEmpty() ) - || ( collectionQueuedOps != null && !collectionQueuedOps.isEmpty() ) || ( collectionRemovals != null && !collectionRemovals.isEmpty() ) - || ( collectionCreations != null && !collectionCreations.isEmpty() ); + return hasUnresolvedEntityInsertActions() + || nonempty( updates ) + || nonempty( insertions ) + || nonempty( deletions ) + || nonempty( collectionUpdates ) + || nonempty( collectionQueuedOps ) + || nonempty( collectionRemovals ) + || nonempty( collectionCreations ); + } + + private boolean nonempty(ExecutableList list) { + return list != null && !list.isEmpty(); } public void unScheduleUnloadedDeletion(Object newEntity) { @@ -866,13 +865,12 @@ public void unScheduleUnloadedDeletion(Object newEntity) { final Object identifier = entityPersister.getIdentifier( newEntity, session ); if ( deletions != null ) { for ( int i = 0; i < deletions.size(); i++ ) { - EntityDeleteAction action = deletions.get( i ); + final EntityDeleteAction action = deletions.get( i ); if ( action.getInstance() == null && action.getEntityName().equals( entityPersister.getEntityName() ) && entityPersister.getIdentifierMapping().areEqual( action.getId(), identifier, session ) ) { - session.getPersistenceContextInternal().removeDeletedUnloadedEntityKey( - session.generateEntityKey( identifier, entityPersister ) - ); + session.getPersistenceContextInternal() + .removeDeletedUnloadedEntityKey( session.generateEntityKey( identifier, entityPersister ) ); deletions.remove( i ); return; } @@ -882,7 +880,7 @@ public void unScheduleUnloadedDeletion(Object newEntity) { } public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) { - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( rescuedEntity ); + final LazyInitializer lazyInitializer = extractLazyInitializer( rescuedEntity ); if ( lazyInitializer != null ) { if ( !lazyInitializer.isUninitialized() ) { rescuedEntity = lazyInitializer.getImplementation( session ); @@ -890,7 +888,7 @@ public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) { } if ( deletions != null ) { for ( int i = 0; i < deletions.size(); i++ ) { - EntityDeleteAction action = deletions.get( i ); + final EntityDeleteAction action = deletions.get( i ); if ( action.getInstance() == rescuedEntity ) { deletions.remove( i ); return; @@ -899,7 +897,7 @@ public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) { } if ( orphanRemovals != null ) { for ( int i = 0; i < orphanRemovals.size(); i++ ) { - EntityDeleteAction action = orphanRemovals.get( i ); + final EntityDeleteAction action = orphanRemovals.get( i ); if ( action.getInstance() == rescuedEntity ) { orphanRemovals.remove( i ); return; @@ -923,7 +921,7 @@ public void serialize(ObjectOutputStream oos) throws IOException { unresolvedInsertions.serialize( oos ); for ( OrderedActions action : ORDERED_OPERATIONS ) { - ExecutableList l = action.getActions( this ); + final ExecutableList l = action.getActions( this ); if ( l == null ) { oos.writeBoolean( false ); } @@ -985,10 +983,9 @@ private AbstractTransactionCompletionProcessQueue(SessionImplementor session) { } public void register(T process) { - if ( process == null ) { - return; + if ( process != null ) { + processes.add( process ); } - processes.add( process ); } public boolean hasActions() { @@ -999,7 +996,9 @@ public boolean hasActions() { /** * Encapsulates behavior needed for before transaction processing */ - private static class BeforeTransactionCompletionProcessQueue extends AbstractTransactionCompletionProcessQueue { + private static class BeforeTransactionCompletionProcessQueue + extends AbstractTransactionCompletionProcessQueue { + private BeforeTransactionCompletionProcessQueue(SessionImplementor session) { super( session ); } @@ -1111,26 +1110,26 @@ public InsertInfo(AbstractEntityInsertAction insertAction, int index) { public void buildDirectDependencies(IdentityHashMap insertInfosByEntity) { final Object[] propertyValues = insertAction.getState(); final Type[] propertyTypes = insertAction.getPersister().getPropertyTypes(); - for (int i = 0, propertyTypesLength = propertyTypes.length; i < propertyTypesLength; i++) { - addDirectDependency(propertyTypes[i], propertyValues[i], insertInfosByEntity); + for ( int i = 0, propertyTypesLength = propertyTypes.length; i < propertyTypesLength; i++ ) { + addDirectDependency( propertyTypes[i], propertyValues[i], insertInfosByEntity ); } } public void propagateChildDependencies() { if ( outgoingDependencies != null ) { - for (InsertInfo childDependency : outgoingDependencies) { + for ( InsertInfo childDependency : outgoingDependencies ) { if (childDependency.transitiveIncomingDependencies == null) { childDependency.transitiveIncomingDependencies = new HashSet<>(); } - childDependency.transitiveIncomingDependencies.add(this); + childDependency.transitiveIncomingDependencies.add( this ); } } } public void buildTransitiveDependencies(Set visited) { - if (transitiveIncomingDependencies != null) { - visited.addAll(transitiveIncomingDependencies); - for (InsertInfo insertInfo : transitiveIncomingDependencies.toArray(new InsertInfo[0])) { + if ( transitiveIncomingDependencies != null ) { + visited.addAll( transitiveIncomingDependencies ); + for ( InsertInfo insertInfo : transitiveIncomingDependencies.toArray(new InsertInfo[0]) ) { insertInfo.addTransitiveDependencies(this, visited); } visited.clear(); @@ -1138,11 +1137,11 @@ public void buildTransitiveDependencies(Set visited) { } public void addTransitiveDependencies(InsertInfo origin, Set visited) { - if (transitiveIncomingDependencies != null) { - for (InsertInfo insertInfo : transitiveIncomingDependencies) { - if (visited.add(insertInfo)) { - origin.transitiveIncomingDependencies.add(insertInfo); - insertInfo.addTransitiveDependencies(origin, visited); + if ( transitiveIncomingDependencies != null ) { + for ( InsertInfo insertInfo : transitiveIncomingDependencies ) { + if ( visited.add(insertInfo) ) { + origin.transitiveIncomingDependencies.add( insertInfo ); + insertInfo.addTransitiveDependencies( origin, visited ); } } } @@ -1151,21 +1150,22 @@ public void addTransitiveDependencies(InsertInfo origin, Set visited private void addDirectDependency(Type type, Object value, IdentityHashMap insertInfosByEntity) { if ( type.isEntityType() && value != null ) { final EntityType entityType = (EntityType) type; - final InsertInfo insertInfo = insertInfosByEntity.get(value); - if (insertInfo != null) { - if (entityType.isOneToOne() && OneToOneType.class.cast( entityType).getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT) { - if (!entityType.isReferenceToPrimaryKey()) { - if (outgoingDependencies == null) { + final InsertInfo insertInfo = insertInfosByEntity.get( value ); + if ( insertInfo != null ) { + if ( entityType.isOneToOne() + && entityType.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) { + if ( !entityType.isReferenceToPrimaryKey() ) { + if ( outgoingDependencies == null ) { outgoingDependencies = new HashSet<>(); } outgoingDependencies.add(insertInfo); } } else { - if (transitiveIncomingDependencies == null) { + if ( transitiveIncomingDependencies == null ) { transitiveIncomingDependencies = new HashSet<>(); } - transitiveIncomingDependencies.add(insertInfo); + transitiveIncomingDependencies.add( insertInfo ); } } } @@ -1176,7 +1176,8 @@ else if ( type.isCollectionType() && value != null ) { .getMappingMetamodel() .getCollectionDescriptor( collectionType.getRole() ) .getAttributeMapping(); - // We only care about mappedBy one-to-many associations, because for these, the elements depend on the collection owner + // We only care about mappedBy one-to-many associations, because for these, + // the elements depend on the collection owner if ( pluralAttributeMapping.getCollectionDescriptor().isOneToMany() && pluralAttributeMapping.getElementDescriptor() instanceof EntityCollectionPart ) { final Iterator elementsIterator = collectionType.getElementsIterator( value ); @@ -1194,29 +1195,28 @@ else if ( type.isCollectionType() && value != null ) { } else if ( type.isComponentType() && value != null ) { // Support recursive checks of composite type properties for associations and collections. - CompositeType compositeType = (CompositeType) type; + final CompositeType compositeType = (CompositeType) type; final SharedSessionContractImplementor session = insertAction.getSession(); - Object[] componentValues = compositeType.getPropertyValues( value, session ); + final Object[] componentValues = compositeType.getPropertyValues( value, session ); for ( int j = 0; j < componentValues.length; ++j ) { - Type componentValueType = compositeType.getSubtypes()[j]; - Object componentValue = componentValues[j]; - addDirectDependency( componentValueType, componentValue, insertInfosByEntity); + final Type componentValueType = compositeType.getSubtypes()[j]; + final Object componentValue = componentValues[j]; + addDirectDependency( componentValueType, componentValue, insertInfosByEntity ); } } } @Override public boolean equals(Object o) { - if (this == o) { + if ( this == o ) { return true; } - if (o == null || getClass() != o.getClass()) { + if ( o == null || getClass() != o.getClass() ) { return false; } - InsertInfo that = (InsertInfo) o; - - return insertAction.equals(that.insertAction); + final InsertInfo that = (InsertInfo) o; + return insertAction.equals( that.insertAction ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java index 65b90d6489..f398eb7fae 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java @@ -1272,20 +1272,13 @@ public JpaCriteriaParameter parameter(Class paramClass) { @Override public JpaCriteriaParameter parameter(Class paramClass, String name) { final BasicType basicType = getTypeConfiguration().getBasicTypeForJavaType( paramClass ); - if ( basicType == null ) { - final BindableType parameterType; - if ( Collection.class.isAssignableFrom( paramClass ) ) { - // a Collection-valued, multi-valued parameter - parameterType = new MultiValueParameterType<>( (Class) Collection.class ); - } - else { - parameterType = null; - } - return new JpaCriteriaParameter<>( name, parameterType, true, this ); - } - else { - return new JpaCriteriaParameter<>( name, basicType, false, this ); - } + boolean notBasic = basicType == null; + final BindableType parameterType = + notBasic && Collection.class.isAssignableFrom( paramClass ) + // a Collection-valued, multi-valued parameter + ? new MultiValueParameterType<>( (Class) Collection.class ) + : basicType; + return new JpaCriteriaParameter<>( name, parameterType, notBasic, this ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java index 194c763db5..240adfe368 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/AbstractType.java @@ -16,12 +16,16 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; /** - * Abstract superclass of the built in Type hierarchy. + * Abstract superclass of the built-in {@link Type} hierarchy. * * @author Gavin King */ public abstract class AbstractType implements Type { + + @Deprecated(forRemoval = true) protected static final Size LEGACY_DICTATED_SIZE = new Size(); + + @Deprecated(forRemoval = true) protected static final Size LEGACY_DEFAULT_SIZE = new Size( 19, 2, 255L, Size.LobMultiplier.NONE ); // to match legacy behavior @Override @@ -44,46 +48,32 @@ public boolean isEntityType() { return false; } - @Override + @Override @SuppressWarnings({"rawtypes", "unchecked"}) public int compare(Object x, Object y) { return ( (Comparable) x ).compareTo(y); } @Override public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) - throws HibernateException { - - if (value==null) { - return null; - } - else { - return (Serializable) deepCopy( value, session.getFactory() ); - } + throws HibernateException { + return value == null ? null : (Serializable) deepCopy( value, session.getFactory() ); } @Override - public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory) throws HibernateException { - if ( value == null ) { - return null; - } - else { - return (Serializable) deepCopy( value, sessionFactory ); - } + public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory) + throws HibernateException { + return value == null ? null : (Serializable) deepCopy( value, sessionFactory ); } @Override public Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) throws HibernateException { - if ( cached==null ) { - return null; - } - else { - return deepCopy( cached, session.getFactory() ); - } + return cached == null ? null : deepCopy( cached, session.getFactory() ); } @Override - public boolean isDirty(Object old, Object current, SharedSessionContractImplementor session) throws HibernateException { + public boolean isDirty(Object old, Object current, SharedSessionContractImplementor session) + throws HibernateException { return !isSame( old, current ); } @@ -94,8 +84,8 @@ public boolean isAnyType() { @Override public boolean isModified(Object old, Object current, boolean[] checkable, SharedSessionContractImplementor session) - throws HibernateException { - return isDirty(old, current, session); + throws HibernateException { + return isDirty( old, current, session ); } @Override @@ -115,12 +105,12 @@ public int getHashCode(Object x) { @Override public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) { - return isEqual(x, y ); + return isEqual( x, y ); } @Override public int getHashCode(Object x, SessionFactoryImplementor factory) { - return getHashCode(x ); + return getHashCode( x ); } @Override @@ -132,24 +122,19 @@ public Object replace( Map copyCache, ForeignKeyDirection foreignKeyDirection) throws HibernateException { - boolean include; + return needsReplacement( foreignKeyDirection ) ? replace( original, target, session, owner, copyCache ) : target; + } + + private boolean needsReplacement(ForeignKeyDirection foreignKeyDirection) { if ( isAssociationType() ) { - AssociationType atype = (AssociationType) this; - include = atype.getForeignKeyDirection()==foreignKeyDirection; + final AssociationType associationType = (AssociationType) this; + return associationType.getForeignKeyDirection() == foreignKeyDirection; } else { - include = ForeignKeyDirection.FROM_PARENT ==foreignKeyDirection; + return ForeignKeyDirection.FROM_PARENT == foreignKeyDirection; } - return include ? replace(original, target, session, owner, copyCache) : target; } @Override public void beforeAssemble(Serializable cached, SharedSessionContractImplementor session) {} - - /*public Object copy(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) - throws HibernateException { - if (original==null) return null; - return assemble( disassemble(original, session), session, owner ); - }*/ - } diff --git a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java index e481a75153..51e475f43a 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/ComponentType.java @@ -19,6 +19,7 @@ import org.hibernate.MappingException; import org.hibernate.PropertyNotFoundException; import org.hibernate.Remove; +import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.engine.spi.CascadeStyle; @@ -26,11 +27,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.Generator; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; @@ -39,12 +40,15 @@ import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; import org.hibernate.resource.beans.spi.ManagedBeanRegistry; +import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.CompositeTypeImplementor; import org.hibernate.usertype.CompositeUserType; +import static org.hibernate.internal.util.ReflectHelper.isRecord; + /** - * Handles "component" mappings + * Handles {@linkplain jakarta.persistence.Embedded embedded} mappings. * * @author Gavin King */ @@ -63,15 +67,14 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen private final boolean isAggregate; private final boolean isKey; private boolean hasNotNullProperty; - private final CompositeUserType compositeUserType; + + @SuppressWarnings("rawtypes") + private final CompositeUserType compositeUserType; private EmbeddableValuedModelPart mappingModelPart; public ComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) { - this.componentClass = component.isDynamic() - ? Map.class - : component.getComponentClass(); - + this.componentClass = component.isDynamic() ? Map.class : component.getComponentClass(); this.isAggregate = component.getAggregateColumn() != null; this.isKey = component.isKey(); this.propertySpan = component.getPropertySpan(); @@ -95,26 +98,22 @@ public ComponentType(Component component, int[] originalPropertyOrder, MetadataB i++; } - if ( component.getTypeName() != null ) { - final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext() - .getServiceRegistry() - .getService( ManagedBeanRegistry.class ); - final Class> customTypeClass = buildingContext.getBootstrapContext() - .getClassLoaderAccess() - .classForName( component.getTypeName() ); - if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) { - //noinspection unchecked,rawtypes - this.compositeUserType = (CompositeUserType) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass ); - } - else { - //noinspection unchecked,rawtypes - this.compositeUserType = (CompositeUserType) beanRegistry.getBean( customTypeClass ).getBeanInstance(); - } + this.compositeUserType = + component.getTypeName() == null ? null : createCompositeUserType( component, buildingContext ); + this.mutable = !isRecord( componentClass ) && ( compositeUserType == null || compositeUserType.isMutable() ); + } + + private static CompositeUserType createCompositeUserType(Component component, MetadataBuildingContext buildingContext) { + final BootstrapContext bootstrapContext = buildingContext.getBootstrapContext(); + final Class> customTypeClass = + bootstrapContext.getClassLoaderAccess().classForName( component.getTypeName() ); + if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) { + return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass ); } else { - this.compositeUserType = null; + return bootstrapContext.getServiceRegistry().requireService( ManagedBeanRegistry.class ) + .getBean( customTypeClass ).getBeanInstance(); } - this.mutable = !ReflectHelper.isRecord( componentClass ) && ( compositeUserType == null || compositeUserType.isMutable() ); } private boolean isAggregate() { @@ -137,7 +136,7 @@ public int getColumnSpan(Mapping mapping) throws MappingException { @Override public int[] getSqlTypeCodes(Mapping mapping) throws MappingException { //Not called at runtime so doesn't matter if it's slow :) - int[] sqlTypes = new int[getColumnSpan( mapping )]; + final int[] sqlTypes = new int[getColumnSpan( mapping )]; int n = 0; for ( int i = 0; i < propertySpan; i++ ) { int[] subtypes = propertyTypes[i].getSqlTypeCodes( mapping ); @@ -164,8 +163,8 @@ public boolean isSame(Object x, Object y) throws HibernateException { return true; } // null value and empty component are considered equivalent - Object[] xvalues = getPropertyValues( x ); - Object[] yvalues = getPropertyValues( y ); + final Object[] xvalues = getPropertyValues( x ); + final Object[] yvalues = getPropertyValues( y ); for ( int i = 0; i < propertySpan; i++ ) { if ( !propertyTypes[i].isSame( xvalues[i], yvalues[i] ) ) { return false; @@ -248,7 +247,7 @@ public int getHashCode(final Object x) { } int result = 17; for ( int i = 0; i < propertySpan; i++ ) { - Object y = getPropertyValue( x, i ); + final Object y = getPropertyValue( x, i ); result *= 37; if ( y != null ) { result += propertyTypes[i].getHashCode( y ); @@ -264,7 +263,7 @@ public int getHashCode(final Object x, final SessionFactoryImplementor factory) } int result = 17; for ( int i = 0; i < propertySpan; i++ ) { - Object y = getPropertyValue( x, i ); + final Object y = getPropertyValue( x, i ); result *= 37; if ( y != null ) { result += propertyTypes[i].getHashCode( y, factory ); @@ -304,7 +303,7 @@ public boolean isDirty(final Object x, final Object y, final boolean[] checkable } } else { - boolean[] subcheckable = new boolean[len]; + final boolean[] subcheckable = new boolean[len]; System.arraycopy( checkable, loc, subcheckable, 0, len ); final boolean dirty = propertyTypes[i].isDirty( getPropertyValue( x, i ), @@ -333,8 +332,8 @@ public boolean isModified( // null value and empty components are considered equivalent int loc = 0; for ( int i = 0; i < propertySpan; i++ ) { - int len = propertyTypes[i].getColumnSpan( session.getFactory() ); - boolean[] subcheckable = new boolean[len]; + final int len = propertyTypes[i].getColumnSpan( session.getFactory() ); + final boolean[] subcheckable = new boolean[len]; System.arraycopy( checkable, loc, subcheckable, 0, len ); if ( propertyTypes[i].isModified( getPropertyValue( old, i ), getPropertyValue( current, i ), subcheckable, session ) ) { return true; @@ -366,7 +365,7 @@ public void nullSafeSet( SharedSessionContractImplementor session) throws HibernateException, SQLException { - Object[] subvalues = nullSafeGetValues( value ); + final Object[] subvalues = nullSafeGetValues( value ); int loc = 0; for ( int i = 0; i < propertySpan; i++ ) { int len = propertyTypes[i].getColumnSpan( session.getFactory() ); @@ -381,7 +380,7 @@ else if ( len == 1 ) { } } else { - boolean[] subsettable = new boolean[len]; + final boolean[] subsettable = new boolean[len]; System.arraycopy( settable, loc, subsettable, 0, len ); propertyTypes[i].nullSafeSet( st, subvalues[i], begin, subsettable, session ); begin += ArrayHelper.countTrue( subsettable ); @@ -409,18 +408,15 @@ public Object getPropertyValue(Object component, int i) { if ( component == null ) { return null; } - - if ( component instanceof Object[] ) { + else if ( component instanceof Object[] ) { // A few calls to hashCode pass the property values already in an // Object[] (ex: QueryKey hash codes for cached queries). // It's easiest to just check for the condition here prior to // trying reflection. - return ( (Object[]) component )[i]; + return ((Object[]) component)[i]; } else { - return mappingModelPart - .getEmbeddableTypeDescriptor() - .getValue( component, i ); + return embeddableTypeDescriptor().getValue( component, i ); } } @@ -442,15 +438,13 @@ else if ( component instanceof Object[] ) { return (Object[]) component; } else { - return mappingModelPart - .getEmbeddableTypeDescriptor() - .getValues( component ); + return embeddableTypeDescriptor().getValues( component ); } } @Override public void setPropertyValues(Object component, Object[] values) { - mappingModelPart.getEmbeddableTypeDescriptor().setValues( component, values ); + embeddableTypeDescriptor().setValues( component, values ); } @Override @@ -475,8 +469,8 @@ public String toLoggableString(Object value, SessionFactoryImplementor factory) return "null"; } - Map result = new HashMap<>(); - Object[] values = getPropertyValues( value ); + final Map result = new HashMap<>(); + final Object[] values = getPropertyValues( value ); for ( int i = 0; i < propertyTypes.length; i++ ) { if ( values[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { result.put( propertyNames[i], "" ); @@ -507,10 +501,7 @@ public Object deepCopy(Object component, SessionFactoryImplementor factory) { values[i] = propertyTypes[i].deepCopy( values[i], factory ); } - final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator(); - Object result = instantiator.instantiate( () -> values, factory ); + final Object result = instantiator().instantiate( () -> values, factory ); //not absolutely necessary, but helps for some //equals()/hashCode() implementations @@ -561,10 +552,8 @@ public Object replace( ); if ( target == null ) { - final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator(); - return instantiator.instantiate( () -> replacedValues, session.getSessionFactory() ); + return instantiator() + .instantiate( () -> replacedValues, session.getSessionFactory() ); } else { setPropertyValues( target, replacedValues ); @@ -592,7 +581,6 @@ public Object replace( } //if ( original == target ) return target; - final Object[] originalValues = getPropertyValues( original ); final Object[] resultValues; @@ -614,10 +602,7 @@ public Object replace( ); if ( target == null ) { - final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator(); - return instantiator.instantiate( () -> replacedValues, session.getSessionFactory() ); + return instantiator().instantiate( () -> replacedValues, session.getSessionFactory() ); } else { setPropertyValues( target, replacedValues ); @@ -638,7 +623,6 @@ public boolean isMutable() { @Override public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException { - if ( value == null ) { return null; } @@ -646,7 +630,7 @@ else if ( compositeUserType != null ) { return compositeUserType.disassemble( value ); } else { - Object[] values = getPropertyValues( value ); + final Object[] values = getPropertyValues( value ); for ( int i = 0; i < propertyTypes.length; i++ ) { values[i] = propertyTypes[i].disassemble( values[i], session, owner ); } @@ -663,7 +647,7 @@ else if ( compositeUserType != null ) { return compositeUserType.disassemble( value ); } else { - Object[] values = getPropertyValues( value ); + final Object[] values = getPropertyValues( value ); for ( int i = 0; i < propertyTypes.length; i++ ) { values[i] = propertyTypes[i].disassemble( values[i], sessionFactory ); } @@ -682,16 +666,13 @@ else if ( compositeUserType != null ) { return compositeUserType.assemble( object, owner ); } else { - Object[] values = (Object[]) object; - Object[] assembled = new Object[values.length]; + final Object[] values = (Object[]) object; + final Object[] assembled = new Object[values.length]; for ( int i = 0; i < propertyTypes.length; i++ ) { assembled[i] = propertyTypes[i].assemble( (Serializable) values[i], session, owner ); } - final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator(); - return instantiator.instantiate( () -> assembled, session.getFactory() ); + return instantiator().instantiate( () -> assembled, session.getFactory() ); } } @@ -707,16 +688,15 @@ public boolean[] getPropertyNullability() { @Override public boolean[] toColumnNullness(Object value, Mapping mapping) { - boolean[] result = new boolean[getColumnSpan( mapping )]; - if ( value == null ) { - return result; - } - Object[] values = getPropertyValues( value ); //TODO!!!!!!! - int loc = 0; - for ( int i = 0; i < propertyTypes.length; i++ ) { - boolean[] propertyNullness = propertyTypes[i].toColumnNullness( values[i], mapping ); - System.arraycopy( propertyNullness, 0, result, loc, propertyNullness.length ); - loc += propertyNullness.length; + final boolean[] result = new boolean[getColumnSpan( mapping )]; + if ( value != null ) { + final Object[] values = getPropertyValues( value ); //TODO!!!!!!! + int loc = 0; + for ( int i = 0; i < propertyTypes.length; i++ ) { + final boolean[] propertyNullness = propertyTypes[i].toColumnNullness( values[i], mapping ); + System.arraycopy( propertyNullness, 0, result, loc, propertyNullness.length ); + loc += propertyNullness.length; + } } return result; } @@ -728,7 +708,7 @@ public boolean isEmbedded() { @Override public int getPropertyIndex(String name) { - String[] names = getPropertyNames(); + final String[] names = getPropertyNames(); for ( int i = 0, max = names.length; i < max; i++ ) { if ( names[i].equals( name ) ) { return i; @@ -756,7 +736,7 @@ public boolean canDoExtraction() { @Override public JdbcType getJdbcType() { - final SelectableMapping aggregateMapping = mappingModelPart.getEmbeddableTypeDescriptor().getAggregateMapping(); + final SelectableMapping aggregateMapping = embeddableTypeDescriptor().getAggregateMapping(); return aggregateMapping == null ? null : aggregateMapping.getJdbcMapping().getJdbcType(); } @@ -776,10 +756,7 @@ private boolean determineIfProcedureParamExtractionCanBePerformed() { public Object extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException { Object[] values; if ( isAggregate() ) { - values = (Object[]) getMappingModelPart().getEmbeddableTypeDescriptor().getAggregateMapping() - .getJdbcMapping() - .getJdbcValueExtractor() - .extract( statement, startIndex, session ); + values = (Object[]) jdbcValueExtractor().extract( statement, startIndex, session ); } else { values = new Object[propertySpan]; @@ -788,8 +765,9 @@ public Object extract(CallableStatement statement, int startIndex, SharedSession for ( int i = 0; i < propertySpan; i++ ) { // we know this cast is safe from canDoExtraction final Type propertyType = propertyTypes[i]; - final Object value = ( (ProcedureParameterExtractionAware) propertyType ) - .extract( statement, currentIndex, session ); + final ProcedureParameterExtractionAware extractionAware = + (ProcedureParameterExtractionAware) propertyType; + final Object value = extractionAware.extract( statement, currentIndex, session ); if ( value == null ) { if ( isKey ) { return null; //different nullability rules for pk/fk @@ -813,21 +791,24 @@ public Object extract(CallableStatement statement, int startIndex, SharedSession @Override public Object extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session) throws SQLException { - assert isAggregate(); - final Object[] values = (Object[]) getMappingModelPart().getEmbeddableTypeDescriptor().getAggregateMapping() - .getJdbcMapping() - .getJdbcValueExtractor() - .extract( statement, paramName, session ); - - return resolve( values, session ); + return resolve( (Object[]) jdbcValueExtractor().extract( statement, paramName, session ), session ); } private Object resolve(Object[] value, SharedSessionContractImplementor session) throws HibernateException { - final EmbeddableInstantiator instantiator = mappingModelPart.getEmbeddableTypeDescriptor() - .getRepresentationStrategy() - .getInstantiator(); - return instantiator.instantiate( () -> value, session.getFactory() ); + return instantiator().instantiate( () -> value, session.getFactory() ); + } + + private EmbeddableMappingType embeddableTypeDescriptor() { + return mappingModelPart.getEmbeddableTypeDescriptor(); + } + + private ValueExtractor jdbcValueExtractor() { + return embeddableTypeDescriptor().getAggregateMapping().getJdbcMapping().getJdbcValueExtractor(); + } + + private EmbeddableInstantiator instantiator() { + return embeddableTypeDescriptor().getRepresentationStrategy().getInstantiator(); } @Override @@ -842,12 +823,12 @@ public Class getBindableJavaType() { @Override public SqmExpressible resolveExpressible(SessionFactoryImplementor sessionFactory) { - return sessionFactory.getRuntimeMetamodels().getJpaMetamodel().embeddable( getReturnedClass() ); + return sessionFactory.getJpaMetamodel().embeddable( getReturnedClass() ); } @Override public void injectMappingModelPart(EmbeddableValuedModelPart part, MappingModelCreationProcess process) { - this.mappingModelPart = part; + mappingModelPart = part; } @Override