From 7fc69f9b26e022633343e5c0aa90ce4ab8fa9d1a Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 9 Jan 2025 20:39:59 +0100 Subject: [PATCH] some very minor cleanups to Binders --- .../boot/model/internal/BinderHelper.java | 208 +++++++----------- .../internal/ComponentPropertyHolder.java | 24 +- .../boot/model/internal/EmbeddableBinder.java | 6 +- .../boot/model/internal/InheritanceState.java | 8 +- .../boot/spi/InFlightMetadataCollector.java | 2 +- .../orm/junit/DialectFeatureChecks.java | 2 +- 6 files changed, 94 insertions(+), 156 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java index 3041c8b4de06..dc63223f455d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/BinderHelper.java @@ -6,12 +6,10 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; @@ -33,7 +31,6 @@ import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.PropertyData; -import org.hibernate.internal.log.DeprecationLogger; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Any; import org.hibernate.mapping.AttributeContainer; @@ -52,15 +49,12 @@ import org.hibernate.mapping.Value; import org.hibernate.models.spi.AnnotationTarget; import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.MemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.type.descriptor.java.JavaType; import jakarta.persistence.ConstraintMode; -import jakarta.persistence.Embeddable; -import jakarta.persistence.EmbeddedId; import jakarta.persistence.FetchType; import jakarta.persistence.ForeignKey; import jakarta.persistence.ManyToOne; @@ -68,8 +62,11 @@ import static jakarta.persistence.ConstraintMode.NO_CONSTRAINT; import static jakarta.persistence.ConstraintMode.PROVIDER_DEFAULT; +import static java.util.Collections.addAll; import static org.hibernate.boot.model.internal.AnnotatedColumn.buildColumnOrFormulaFromAnnotation; import static org.hibernate.boot.model.internal.AnyBinder.resolveImplicitDiscriminatorStrategy; +import static org.hibernate.boot.model.internal.ForeignKeyType.NON_PRIMARY_KEY_REFERENCE; +import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotBlank; import static org.hibernate.internal.util.StringHelper.qualifier; @@ -148,15 +145,17 @@ public static void createSyntheticPropertyReference( boolean inverse, MetadataBuildingContext context) { // this work is not necessary for a primary key reference - if ( joinColumns.getReferencedColumnsType( targetEntity ) == ForeignKeyType.NON_PRIMARY_KEY_REFERENCE ) { // && !firstColumn.isImplicit() + if ( joinColumns.getReferencedColumnsType( targetEntity ) == NON_PRIMARY_KEY_REFERENCE ) { // && !firstColumn.isImplicit() // all the columns have to belong to the same table; // figure out which table has the columns by looking // for a PersistentClass or Join in the hierarchy of // the target entity which has the first column - final AttributeContainer columnOwner = findReferencedColumnOwner( targetEntity, joinColumns.getJoinColumns().get(0), context ); + final AttributeContainer columnOwner = + findReferencedColumnOwner( targetEntity, joinColumns.getJoinColumns().get(0), context ); checkColumnInSameTable( joinColumns, targetEntity, associatedEntity, context, columnOwner ); // find all properties mapped to each column - final List properties = findPropertiesByColumns( columnOwner, joinColumns, associatedEntity, context ); + final List properties = + findPropertiesByColumns( columnOwner, joinColumns, associatedEntity, context ); // create a Property along with the new synthetic // Component if necessary (or reuse the existing // Property that matches exactly) @@ -192,13 +191,13 @@ private static void checkColumnInSameTable( PersistentClass targetEntity, PersistentClass associatedEntity, MetadataBuildingContext context, - Object columnOwner) { + AttributeContainer columnOwner) { if ( joinColumns.hasMappedBy() ) { // we should only get called for owning side of association throw new AssertionFailure("no need to create synthetic properties for unowned collections"); } for ( AnnotatedJoinColumn column: joinColumns.getJoinColumns() ) { - final Object owner = findReferencedColumnOwner( targetEntity, column, context ); + final AttributeContainer owner = findReferencedColumnOwner( targetEntity, column, context ); if ( owner == null ) { throw new AnnotationException( "A '@JoinColumn' for association " + associationMessage( associatedEntity, joinColumns ) @@ -261,16 +260,16 @@ private static void registerSyntheticProperty( String propertyName, String syntheticPropertyName, MetadataBuildingContext context) { - if ( value instanceof ToOne ) { - ( (ToOne) value).setReferencedPropertyName( syntheticPropertyName ); - ( (ToOne) value).setReferenceToPrimaryKey( false ); + if ( value instanceof ToOne toOne ) { + toOne.setReferencedPropertyName( syntheticPropertyName ); + toOne.setReferenceToPrimaryKey( false ); context.getMetadataCollector().addUniquePropertyReference( ownerEntity.getEntityName(), syntheticPropertyName ); } - else if ( value instanceof Collection ) { - ( (Collection) value).setReferencedPropertyName( syntheticPropertyName ); + else if ( value instanceof Collection collection ) { + collection.setReferencedPropertyName( syntheticPropertyName ); //not unique because we could create a mtm wo association table context.getMetadataCollector().addPropertyReference( ownerEntity.getEntityName(), @@ -278,16 +277,12 @@ else if ( value instanceof Collection ) { ); } else { - throw new AssertionFailure( - "Do a property ref on an unexpected Value type: " - + value.getClass().getName() - ); + throw new AssertionFailure( "Property ref on an unexpected Value type: " + value.getClass().getName() ); } - context.getMetadataCollector().addPropertyReferencedAssociation( - ( inverse ? "inverse__" : "" ) + associatedClass.getEntityName(), - propertyName, - syntheticPropertyName - ); + final String associatedEntityName = associatedClass.getEntityName(); + final String generatedName = inverse ? "inverse__" + associatedEntityName : associatedEntityName; + context.getMetadataCollector() + .addPropertyReferencedAssociation( generatedName, propertyName, syntheticPropertyName ); } private static String syntheticPropertyName( @@ -306,11 +301,14 @@ private static String associationMessage(PersistentClass associatedEntity, Annot if ( associatedEntity != null ) { return "'" + associatedEntity.getEntityName() + "." + joinColumns.getPropertyName() + "'"; } - else if ( joinColumns.getPropertyHolder() != null ) { - return "'" + joinColumns.getPropertyHolder().getEntityName() + "." + joinColumns.getPropertyName() + "'"; - } else { - return ""; + final PropertyHolder propertyHolder = joinColumns.getPropertyHolder(); + if ( propertyHolder != null ) { + return "'" + propertyHolder.getEntityName() + "." + joinColumns.getPropertyName() + "'"; + } + else { + return ""; + } } } @@ -392,7 +390,7 @@ private static Property cloneProperty(PersistentClass ownerEntity, MetadataBuild * and other attributes. */ public static Property shallowCopy(Property property) { - Property clone = new SyntheticProperty(); + final Property clone = new SyntheticProperty(); clone.setCascade( property.getCascade() ); clone.setInsertable( property.isInsertable() ); clone.setLazy( property.isLazy() ); @@ -409,25 +407,12 @@ public static Property shallowCopy(Property property) { } private static List findPropertiesByColumns( - Object columnOwner, + AttributeContainer columnOwner, AnnotatedJoinColumns columns, PersistentClass associatedEntity, MetadataBuildingContext context) { - final Table referencedTable; - if ( columnOwner instanceof PersistentClass ) { - referencedTable = ( (PersistentClass) columnOwner ).getTable(); - } - else if ( columnOwner instanceof Join ) { - referencedTable = ( (Join) columnOwner ).getTable(); - } - else { - throw new AssertionFailure( - columnOwner == null ? - "columnOwner is null" : - "columnOwner neither PersistentClass nor Join: " + columnOwner.getClass() - ); - } + final Table referencedTable = columnOwner.getTable(); // Build the list of column names in the exact order they were // specified by the @JoinColumn annotations. @@ -923,16 +908,18 @@ public static String getCascadeStrategy( boolean orphanRemoval, MetadataBuildingContext context) { final EnumSet cascadeTypes = convertToHibernateCascadeType( ejbCascades ); - final CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null - ? null - : hibernateCascadeAnnotation.value(); + final CascadeType[] hibernateCascades = + hibernateCascadeAnnotation == null ? null : hibernateCascadeAnnotation.value(); if ( !isEmpty( hibernateCascades ) ) { - Collections.addAll( cascadeTypes, hibernateCascades ); + addAll( cascadeTypes, hibernateCascades ); } if ( orphanRemoval ) { cascadeTypes.add( CascadeType.DELETE_ORPHAN ); cascadeTypes.add( CascadeType.REMOVE ); } + if ( cascadeTypes.contains( CascadeType.REPLICATE ) ) { + warnAboutDeprecatedCascadeType( CascadeType.REPLICATE ); + } cascadeTypes.addAll( context.getEffectiveDefaults().getDefaultCascadeTypes() ); return renderCascadeTypeList( cascadeTypes ); } @@ -960,68 +947,31 @@ private static CascadeType convertCascadeType(jakarta.persistence.CascadeType ca private static String renderCascadeTypeList(EnumSet cascadeTypes) { final StringBuilder cascade = new StringBuilder(); - for ( CascadeType cascadeType : cascadeTypes) { - switch ( cascadeType ) { - case ALL: - cascade.append( "," ).append( "all" ); - break; - case PERSIST: - cascade.append( "," ).append( "persist" ); - break; - case MERGE: - cascade.append( "," ).append( "merge" ); - break; - case LOCK: - cascade.append( "," ).append( "lock" ); - break; - case REFRESH: - cascade.append( "," ).append( "refresh" ); - break; - case DETACH: - cascade.append( "," ).append( "evict" ); - break; - case REMOVE: - cascade.append( "," ).append( "delete" ); - break; - case DELETE_ORPHAN: - cascade.append( "," ).append( "delete-orphan" ); - break; - case REPLICATE: - warnAboutDeprecatedCascadeType( CascadeType.REPLICATE ); - cascade.append( "," ).append( "replicate" ); - break; - } + for ( CascadeType cascadeType : cascadeTypes ) { + cascade.append( "," ); + cascade.append( switch ( cascadeType ) { + case ALL -> "all"; + case PERSIST -> "persist"; + case MERGE -> "merge"; + case LOCK -> "lock"; + case REFRESH -> "refresh"; + case DETACH -> "evict"; + case REMOVE -> "delete"; + case DELETE_ORPHAN -> "delete-orphan"; + case REPLICATE -> "replicate"; + } ); } return cascade.isEmpty() ? "none" : cascade.substring(1); } private static void warnAboutDeprecatedCascadeType(CascadeType cascadeType) { - DeprecationLogger.DEPRECATION_LOGGER.warnf( - "%s.%s is deprecated", - CascadeType.class.getName(), - cascadeType.name().toLowerCase( Locale.ROOT ) - ); - } - - private static void warnAboutDeprecatedCascadeType(CascadeType oldType, CascadeType newType) { - DeprecationLogger.DEPRECATION_LOGGER.warnf( - "%s.%s is deprecated, use %s.%s instead", - CascadeType.class.getName(), - oldType.name().toLowerCase( Locale.ROOT ), - CascadeType.class.getName(), - newType.name().toLowerCase( Locale.ROOT ) - ); + DEPRECATION_LOGGER.warnf( "CascadeType.%s is deprecated", cascadeType.name() ); } static boolean isGlobalGeneratorNameGlobal(MetadataBuildingContext context) { return context.getBootstrapContext().getJpaCompliance().isGlobalGeneratorScopeEnabled(); } - static boolean isCompositeId(ClassDetails idClass, MemberDetails idProperty) { - return idClass.hasDirectAnnotationUsage( Embeddable.class ) - || idProperty.hasDirectAnnotationUsage( EmbeddedId.class ); - } - public static boolean isDefault(ClassDetails clazz) { return clazz == ClassDetails.VOID_CLASS_DETAILS; } @@ -1036,33 +986,38 @@ public static void checkMappedByType( String propertyName, PropertyHolder propertyHolder, Map persistentClasses) { - final ToOne toOne; - if ( targetValue instanceof Collection ) { - toOne = (ToOne) ( (Collection) targetValue ).getElement(); + if ( targetValue instanceof Collection collection ) { + final ToOne element = (ToOne) collection.getElement(); + checkMappedByType( mappedBy, propertyName, propertyHolder, persistentClasses, element ); } - else if ( targetValue instanceof ToOne ) { - toOne = (ToOne) targetValue; - } - else { - // Nothing to check, EARLY EXIT - return; + else if ( targetValue instanceof ToOne toOne ) { + checkMappedByType( mappedBy, propertyName, propertyHolder, persistentClasses, toOne ); } + } + + private static void checkMappedByType( + String mappedBy, + String propertyName, + PropertyHolder propertyHolder, + Map persistentClasses, + ToOne toOne) { final String referencedEntityName = toOne.getReferencedEntityName(); final PersistentClass referencedClass = persistentClasses.get( referencedEntityName ); PersistentClass ownerClass = propertyHolder.getPersistentClass(); while ( ownerClass != null ) { if ( checkReferencedClass( ownerClass, referencedClass ) ) { + // the two entities map to the same table + // so we are good return; } - else { - ownerClass = ownerClass.getSuperPersistentClass(); - } + ownerClass = ownerClass.getSuperPersistentClass(); } + // we could not find any entity mapping to the same table throw new AnnotationException( "Association '" + qualify( propertyHolder.getPath(), propertyName ) - + "' is 'mappedBy' a property named '" + mappedBy - + "' which references the wrong entity type '" + referencedEntityName - + "', expected '" + propertyHolder.getEntityName() + "'" + + "' is 'mappedBy' a property named '" + mappedBy + + "' which references the wrong entity type '" + referencedEntityName + + "', expected '" + propertyHolder.getEntityName() + "'" ); } @@ -1111,21 +1066,20 @@ public static A extractFromPackage( final String declaringClassName = classDetails.getName(); final String packageName = qualifier( declaringClassName ); - if ( isEmpty( packageName ) ) { return null; } - final SourceModelBuildingContext sourceModelContext = context.getMetadataCollector().getSourceModelBuildingContext(); - final ClassDetailsRegistry classDetailsRegistry = sourceModelContext.getClassDetailsRegistry(); - - final String packageInfoName = packageName + ".package-info"; - try { - final ClassDetails packageInfoClassDetails = classDetailsRegistry.resolveClassDetails( packageInfoName ); - return packageInfoClassDetails.getAnnotationUsage( annotationType, sourceModelContext ); - } - catch (ClassLoadingException ignore) { + else { + final SourceModelBuildingContext sourceModelContext = + context.getMetadataCollector().getSourceModelBuildingContext(); + try { + return sourceModelContext.getClassDetailsRegistry() + .resolveClassDetails( packageName + ".package-info" ) + .getAnnotationUsage( annotationType, sourceModelContext ); + } + catch (ClassLoadingException ignore) { + return null; + } } - - return null; } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ComponentPropertyHolder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ComponentPropertyHolder.java index 2b6de2988088..11d3d8db1edb 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ComponentPropertyHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/ComponentPropertyHolder.java @@ -4,7 +4,6 @@ */ package org.hibernate.boot.model.internal; -import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Map; @@ -24,12 +23,11 @@ import jakarta.persistence.Column; import jakarta.persistence.Convert; -import jakarta.persistence.EmbeddedId; -import jakarta.persistence.Id; import jakarta.persistence.JoinTable; import static org.hibernate.boot.model.internal.ClassPropertyHolder.addPropertyToMappedSuperclass; import static org.hibernate.boot.model.internal.ClassPropertyHolder.handleGenericComponentProperty; +import static org.hibernate.boot.model.internal.PropertyBinder.hasIdAnnotation; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.qualifyConditionally; import static org.hibernate.spi.NavigablePath.IDENTIFIER_MAPPER_PROPERTY; @@ -83,7 +81,7 @@ public ComponentPropertyHolder( setCurrentProperty( embeddedMemberDetails ); this.component = component; this.isOrWithinEmbeddedId = parent.isOrWithinEmbeddedId() - || hasAnnotation( embeddedMemberDetails, Id.class, EmbeddedId.class ); + || embeddedMemberDetails != null && hasIdAnnotation( embeddedMemberDetails ); this.isWithinElementCollection = parent.isWithinElementCollection() || parent instanceof CollectionPropertyHolder; this.inheritanceStatePerClass = inheritanceStatePerClass; @@ -98,24 +96,6 @@ public ComponentPropertyHolder( } } - private boolean hasAnnotation( - MemberDetails memberDetails, - Class annotationType) { - if ( memberDetails == null ) { - return false; - } - - return memberDetails.hasDirectAnnotationUsage( annotationType ); - } - - private boolean hasAnnotation( - MemberDetails memberDetails, - Class annotationType1, - Class annotationType2) { - return hasAnnotation( memberDetails, annotationType1 ) - || hasAnnotation( memberDetails, annotationType2 ); - } - /** * This is called from our constructor and handles (in order):
    *
  1. @Convert annotation at the Embeddable class level
  2. diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java index 0070edcdda2e..f7c2ea568b83 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java @@ -224,11 +224,13 @@ private static Component bindOverriddenEmbeddable( static boolean isEmbedded(MemberDetails property, ClassDetails returnedClass) { return property.hasDirectAnnotationUsage( Embedded.class ) || property.hasDirectAnnotationUsage( EmbeddedId.class ) - || returnedClass.hasDirectAnnotationUsage( Embeddable.class ) && !property.hasDirectAnnotationUsage( Convert.class ); + || returnedClass.hasDirectAnnotationUsage( Embeddable.class ) + && !property.hasDirectAnnotationUsage( Convert.class ); } static boolean isEmbedded(MemberDetails property, TypeDetails returnedClass) { - if ( property.hasDirectAnnotationUsage( Embedded.class ) || property.hasDirectAnnotationUsage( EmbeddedId.class ) ) { + if ( property.hasDirectAnnotationUsage( Embedded.class ) + || property.hasDirectAnnotationUsage( EmbeddedId.class ) ) { return true; } else { diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java index cb52313d3626..15a947b6f9eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/InheritanceState.java @@ -32,6 +32,7 @@ import static jakarta.persistence.InheritanceType.SINGLE_TABLE; import static jakarta.persistence.InheritanceType.TABLE_PER_CLASS; import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass; +import static org.hibernate.boot.model.internal.PropertyBinder.hasIdAnnotation; /** * Some extra data to the inheritance position of a class. @@ -274,19 +275,20 @@ private AccessType determineDefaultAccessType() { for ( ClassDetails candidate = classDetails; candidate != null && !Object.class.getName().equals( candidate.getName() ); candidate = candidate.getSuperClass() ) { - if ( candidate.hasDirectAnnotationUsage( Entity.class ) || candidate.hasDirectAnnotationUsage( MappedSuperclass.class ) ) { + if ( candidate.hasDirectAnnotationUsage( Entity.class ) + || candidate.hasDirectAnnotationUsage( MappedSuperclass.class ) ) { for ( MethodDetails method : candidate.getMethods() ) { if ( method.getMethodKind() != MethodDetails.MethodKind.GETTER ) { continue; } - if ( method.hasDirectAnnotationUsage( Id.class ) || method.hasDirectAnnotationUsage( EmbeddedId.class ) ) { + if ( hasIdAnnotation( method ) ) { return AccessType.PROPERTY; } } for ( FieldDetails field : candidate.getFields() ) { - if ( field.hasDirectAnnotationUsage( Id.class ) || field.hasDirectAnnotationUsage( EmbeddedId.class ) ) { + if ( hasIdAnnotation( field ) ) { return AccessType.FIELD; } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java index e793b9b5077b..c175637e494e 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/InFlightMetadataCollector.java @@ -365,7 +365,7 @@ interface DelayedPropertyReferenceHandler extends Serializable { void addPropertyReference(String entityName, String propertyName); void addUniquePropertyReference(String entityName, String propertyName); - void addPropertyReferencedAssociation(String s, String propertyName, String syntheticPropertyName); + void addPropertyReferencedAssociation(String entityName, String propertyName, String syntheticPropertyName); String getPropertyReferencedAssociation(String entityName, String mappedBy); void addMappedBy(String name, String mappedBy, String propertyName); diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java index 86f97c11496b..5f528fe7ed89 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DialectFeatureChecks.java @@ -1606,7 +1606,7 @@ public void addUniquePropertyReference(String entityName, String propertyName) { } @Override - public void addPropertyReferencedAssociation(String s, String propertyName, String syntheticPropertyName) { + public void addPropertyReferencedAssociation(String entityName, String propertyName, String syntheticPropertyName) { }