HHH-17831 make AttributeBinder work for collections and @Any

introduce BatchSizeBinder to prove it works
various cleanups in binders + mapping package
This commit is contained in:
Gavin King 2024-03-10 11:26:43 +01:00
parent 4a70a23212
commit 95ee026cb2
18 changed files with 199 additions and 137 deletions

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.annotations;
import org.hibernate.binder.internal.BatchSizeBinder;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@ -54,6 +56,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
@AttributeBinderType(binder = BatchSizeBinder.class)
@TypeBinderType(binder = BatchSizeBinder.class)
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface BatchSize {

View File

@ -30,8 +30,8 @@ import java.lang.annotation.Annotation;
public interface AttributeBinder<A extends Annotation> {
/**
* Perform some custom configuration of the model relating to the given annotated
* {@link Property} of the given {@link PersistentClass entity class} or
* {@link org.hibernate.mapping.Component embeddable class}.
* {@link Property} of the given {@linkplain PersistentClass entity class} or
* {@linkplain org.hibernate.mapping.Component embeddable class}.
*
* @param annotation an annotation of the property that is declared as an
* {@link org.hibernate.annotations.AttributeBinderType}

View File

@ -55,7 +55,7 @@ import java.lang.annotation.Annotation;
public interface TypeBinder<A extends Annotation> {
/**
* Perform some custom configuration of the model relating to the given annotated
* {@link PersistentClass entity class}.
* {@linkplain PersistentClass entity class}.
*
* @param annotation an annotation of the entity class that is declared as an
* {@link org.hibernate.annotations.TypeBinderType}
@ -64,7 +64,7 @@ public interface TypeBinder<A extends Annotation> {
void bind(A annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass);
/**
* Perform some custom configuration of the model relating to the given annotated
* {@link Component embeddable class}.
* {@linkplain Component embeddable class}.
*
* @param annotation an annotation of the embeddable class that is declared as an
* {@link org.hibernate.annotations.TypeBinderType}

View File

@ -0,0 +1,50 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.binder.internal;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.BatchSize;
import org.hibernate.binder.AttributeBinder;
import org.hibernate.binder.TypeBinder;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value;
/**
* Binder for the {@link BatchSize} annotation.
*
* @since 6.5
*
* @author Gavin King
*/
public class BatchSizeBinder implements TypeBinder<BatchSize>, AttributeBinder<BatchSize> {
@Override
public void bind(BatchSize batchSize, MetadataBuildingContext context, PersistentClass persistentClass) {
persistentClass.setBatchSize( batchSize.size() );
}
@Override
public void bind(BatchSize batchSize, MetadataBuildingContext context, Component embeddableClass) {
throw new AnnotationException("Class '" + embeddableClass.getComponentClassName()
+ "' is an '@Embeddable' type and may not be annotated '@BatchSize'");
}
@Override
public void bind(BatchSize batchSize, MetadataBuildingContext context, PersistentClass persistentClass, Property property) {
final Value value = property.getValue();
if ( value instanceof Collection ) {
final Collection collection = (Collection) value;
collection.setBatchSize( batchSize.size() );
}
else {
throw new AnnotationException("Property '" + property.getName() + "' may not be annotated '@BatchSize'");
}
}
}

View File

@ -47,7 +47,6 @@ import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
import org.hibernate.boot.model.convert.spi.RegisteredConversion;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.FilterDefinition;
@ -629,15 +628,15 @@ public final class AnnotationBinder {
}
private static void handleConverterRegistration(ConverterRegistration registration, MetadataBuildingContext context) {
final InFlightMetadataCollector metadataCollector = context.getMetadataCollector();
metadataCollector.getConverterRegistry().addRegisteredConversion(
new RegisteredConversion(
registration.domainType(),
registration.converter(),
registration.autoApply(),
context
)
);
context.getMetadataCollector().getConverterRegistry()
.addRegisteredConversion(
new RegisteredConversion(
registration.domainType(),
registration.converter(),
registration.autoApply(),
context
)
);
}
public static void bindFilterDefs(XAnnotatedElement annotatedElement, MetadataBuildingContext context) {

View File

@ -121,6 +121,9 @@ public class AnyBinder {
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setCascade( cascadeStrategy );
binder.setBuildingContext( context );
binder.setHolder( propertyHolder );
binder.setProperty( property );
binder.setEntityBinder( entityBinder );
Property prop = binder.makeProperty();
prop.setOptional( optional && value.isNullable() );
//composite FK columns are in the same table, so it's OK

View File

@ -21,7 +21,6 @@ import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.Bag;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheLayout;
import org.hibernate.annotations.Cascade;
@ -106,7 +105,6 @@ import org.hibernate.mapping.DependantValue;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.MappingHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
@ -174,6 +172,7 @@ import static org.hibernate.boot.model.internal.BinderHelper.toAliasEntityMap;
import static org.hibernate.boot.model.internal.BinderHelper.toAliasTableMap;
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.HCANNHelper.findAnnotation;
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
import static org.hibernate.boot.model.internal.BinderHelper.extractFromPackage;
import static org.hibernate.boot.model.source.internal.hbm.ModelBinder.useEntityWhereClauseForCollections;
@ -183,6 +182,7 @@ import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
import static org.hibernate.internal.util.StringHelper.qualify;
import static org.hibernate.mapping.MappingHelper.createLocalUserCollectionTypeBean;
/**
* Base class for stateful binders responsible for producing mapping model objects of type {@link Collection}.
@ -209,7 +209,6 @@ public abstract class CollectionBinder {
protected Collection collection;
protected String propertyName;
protected PropertyHolder propertyHolder;
private int batchSize;
private String mappedBy;
private XClass collectionElementType;
private XClass targetEntity;
@ -284,7 +283,6 @@ public abstract class CollectionBinder {
collectionBinder.setIndexColumn( getIndexColumn( propertyHolder, inferredData, entityBinder, context, property ) );
collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );
collectionBinder.setPropertyName( inferredData.getPropertyName() );
collectionBinder.setBatchSize( property.getAnnotation( BatchSize.class ) );
collectionBinder.setJpaOrderBy( property.getAnnotation( OrderBy.class ) );
collectionBinder.setSqlOrderBy( getOverridableAnnotation( property, org.hibernate.annotations.OrderBy.class, context ) );
collectionBinder.setSqlOrder( getOverridableAnnotation( property, SQLOrder.class, context ) );
@ -806,10 +804,6 @@ public abstract class CollectionBinder {
this.propertyHolder = propertyHolder;
}
public void setBatchSize(BatchSize batchSize) {
this.batchSize = batchSize == null ? -1 : batchSize.size();
}
public void setJpaOrderBy(jakarta.persistence.OrderBy jpaOrderBy) {
this.jpaOrderBy = jpaOrderBy;
}
@ -839,7 +833,7 @@ public abstract class CollectionBinder {
MetadataBuildingContext buildingContext) {
final CollectionBinder binder;
final CollectionType typeAnnotation = HCANNHelper.findAnnotation( property, CollectionType.class );
final CollectionType typeAnnotation = findAnnotation( property, CollectionType.class );
if ( typeAnnotation != null ) {
binder = createBinderFromCustomTypeAnnotation( property, typeAnnotation, buildingContext );
// todo (6.0) - technically, these should no longer be needed
@ -857,8 +851,8 @@ public abstract class CollectionBinder {
private static CollectionBinder createBinderAutomatically(XProperty property, MetadataBuildingContext context) {
final CollectionClassification classification = determineCollectionClassification( property, context );
final CollectionTypeRegistrationDescriptor typeRegistration = context.getMetadataCollector()
.findCollectionTypeRegistration( classification );
final CollectionTypeRegistrationDescriptor typeRegistration =
context.getMetadataCollector().findCollectionTypeRegistration( classification );
return typeRegistration != null
? createBinderFromTypeRegistration( property, classification, typeRegistration, context )
: createBinderFromProperty( property, context );
@ -890,7 +884,7 @@ public abstract class CollectionBinder {
final boolean hasParameters = CollectionHelper.isNotEmpty( parameters );
if ( !buildingContext.getBuildingOptions().isAllowExtensionsInCdi() ) {
// if deferred container access is enabled, we locally create the user-type
return MappingHelper.createLocalUserCollectionTypeBean( role, implementation, hasParameters, parameters );
return createLocalUserCollectionTypeBean( role, implementation, hasParameters, parameters );
}
final ManagedBean<? extends UserCollectionType> managedBean =
@ -1013,7 +1007,7 @@ public abstract class CollectionBinder {
if ( property.isArray() ) {
return CollectionClassification.ARRAY;
}
else if ( HCANNHelper.findAnnotation( property, Bag.class ) == null ) {
else if ( findAnnotation( property, Bag.class ) == null ) {
return determineCollectionClassification( determineSemanticJavaType( property ), property, buildingContext );
}
else {
@ -1138,7 +1132,6 @@ public abstract class CollectionBinder {
return priorityClass;
}
}
return null;
}
@ -1184,7 +1177,6 @@ public abstract class CollectionBinder {
bindExplicitTypes();
//set laziness
defineFetchingStrategy();
collection.setBatchSize( batchSize );
collection.setMutable( isMutable() );
//work on association
boolean isUnowned = isUnownedCollection();
@ -1320,6 +1312,7 @@ public abstract class CollectionBinder {
binder.setInsertable( insertable );
binder.setUpdatable( updatable );
binder.setBuildingContext( buildingContext );
binder.setHolder( propertyHolder );
Property prop = binder.makeProperty();
//we don't care about the join stuffs because the column is on the association table.
if ( !declaringClassSet ) {

View File

@ -20,7 +20,6 @@ import java.util.Set;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.CacheLayout;
@ -1270,7 +1269,6 @@ public class EntityBinder {
bindOptimisticLocking();
bindPolymorphism();
bindProxy();
bindBatchSize();
bindWhere();
bindCache();
bindNaturalIdCache();
@ -1552,11 +1550,6 @@ public class EntityBinder {
}
}
public void bindBatchSize() {
final BatchSize batchSize = annotatedClass.getAnnotation( BatchSize.class );
persistentClass.setBatchSize(batchSize != null ? batchSize.size() : -1 );
}
public void bindProxy() {
final Proxy proxy = annotatedClass.getAnnotation( Proxy.class );
if ( proxy != null ) {

View File

@ -112,6 +112,7 @@ public class OneToOneSecondPass implements SecondPass {
binder.setCascade( cascadeStrategy );
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setBuildingContext( buildingContext );
binder.setHolder( propertyHolder );
final LazyGroup lazyGroupAnnotation = property.getAnnotation( LazyGroup.class );
if ( lazyGroupAnnotation != null ) {

View File

@ -47,6 +47,7 @@ import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.binder.AttributeBinder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.spi.AccessType;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData;
import org.hibernate.engine.OptimisticLockStyle;
@ -57,6 +58,7 @@ import org.hibernate.mapping.GeneratorCreator;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
@ -123,7 +125,6 @@ public class PropertyBinder {
private EntityBinder entityBinder;
private boolean toMany;
private String referencedEntityName;
// private PropertyAccessStrategy propertyAccessStrategy;
public void setReferencedEntityName(String referencedEntityName) {
this.referencedEntityName = referencedEntityName;
@ -193,10 +194,6 @@ public class PropertyBinder {
this.buildingContext = buildingContext;
}
// public void setPropertyAccessStrategy(PropertyAccessStrategy propertyAccessStrategy) {
// this.propertyAccessStrategy = propertyAccessStrategy;
// }
//
public void setDeclaringClass(XClass declaringClass) {
this.declaringClass = declaringClass;
this.declaringClassSet = true;
@ -265,19 +262,23 @@ public class PropertyBinder {
basicValueBinder.setReferencedEntityName( referencedEntityName );
basicValueBinder.setAccessType( accessType );
value = basicValueBinder.make();
return makeProperty();
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void callAttributeBinders(Property prop) {
for ( Annotation containingAnnotation : findContainingAnnotations(property, AttributeBinderType.class ) ) {
final AttributeBinderType binderType = containingAnnotation.annotationType().getAnnotation( AttributeBinderType.class );
private void callAttributeBinders(Property property, Map<String, PersistentClass> persistentClasses) {
for ( Annotation containingAnnotation : findContainingAnnotations( this.property, AttributeBinderType.class ) ) {
final AttributeBinderType binderType =
containingAnnotation.annotationType().getAnnotation( AttributeBinderType.class );
try {
final AttributeBinder binder = binderType.binder().newInstance();
binder.bind( containingAnnotation, buildingContext, entityBinder.getPersistentClass(), prop );
final PersistentClass persistentClass =
entityBinder != null
? entityBinder.getPersistentClass()
: persistentClasses.get( holder.getEntityName() );
binder.bind( containingAnnotation, buildingContext, persistentClass, property );
}
catch ( Exception e ) {
throw new AnnotationException( "error processing @AttributeBinderType annotation '" + containingAnnotation + "'", e );
@ -301,53 +302,62 @@ public class PropertyBinder {
private Property bind(Property property) {
if ( isId ) {
final RootClass rootClass = (RootClass) holder.getPersistentClass();
if ( toMany || entityBinder.wrapIdsInEmbeddedComponents() ) {
// If an XxxToMany, it has to be wrapped today.
// This poses a problem as the PK is the class instead of the
// associated class which is not really compliant with the spec
//FIXME is it good enough?
getOrCreateCompositeId( rootClass ).addProperty( property );
}
else {
rootClass.setIdentifier( (KeyValue) getValue() );
if ( embedded ) {
rootClass.setEmbeddedIdentifier( true );
}
else {
rootClass.setIdentifierProperty( property );
final MappedSuperclass superclass = getMappedSuperclassOrNull(
declaringClass,
inheritanceStatePerClass,
buildingContext
);
setDeclaredIdentifier( rootClass, superclass, property );
}
}
bindId( property );
}
else {
holder.addProperty( property, columns, declaringClass );
}
if ( buildingContext.getMetadataCollector().isInSecondPass() ) {
callAttributeBinders( property );
}
else {
buildingContext.getMetadataCollector()
.addSecondPass( persistentClasses -> callAttributeBinders( property ) );
}
callAttributeBindersInSecondPass( property );
return property;
}
private void callAttributeBindersInSecondPass(Property property) {
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
if ( metadataCollector.isInSecondPass() ) {
callAttributeBinders( property, metadataCollector.getEntityBindingMap() );
}
else {
metadataCollector.addSecondPass( persistentClasses -> callAttributeBinders( property, persistentClasses ) );
}
}
private void bindId(Property property) {
final RootClass rootClass = (RootClass) holder.getPersistentClass();
if ( toMany || entityBinder.wrapIdsInEmbeddedComponents() ) {
// If an XxxToMany, it has to be wrapped today.
// This poses a problem as the PK is the class instead of the
// associated class which is not really compliant with the spec
//FIXME is it good enough?
getOrCreateCompositeId( rootClass ).addProperty( property );
}
else {
rootClass.setIdentifier( (KeyValue) getValue() );
if ( embedded ) {
rootClass.setEmbeddedIdentifier( true );
}
else {
rootClass.setIdentifierProperty(property);
final MappedSuperclass superclass =
getMappedSuperclassOrNull( declaringClass, inheritanceStatePerClass, buildingContext );
setDeclaredIdentifier( rootClass, superclass, property);
}
}
}
private void setDeclaredIdentifier(RootClass rootClass, MappedSuperclass superclass, Property prop) {
handleGenericComponentProperty( prop, buildingContext );
if ( superclass == null ) {
rootClass.setDeclaredIdentifierProperty( prop );
return;
}
final Class<?> type = buildingContext.getBootstrapContext().getReflectionManager().toClass( declaringClass );
prepareActualProperty( prop, type, false, buildingContext, superclass::setDeclaredIdentifierProperty );
else {
final Class<?> type =
buildingContext.getBootstrapContext().getReflectionManager()
.toClass( declaringClass );
prepareActualProperty( prop, type, false, buildingContext,
superclass::setDeclaredIdentifierProperty );
}
}
private Component getOrCreateCompositeId(RootClass rootClass) {
@ -355,7 +365,7 @@ public class PropertyBinder {
if ( id == null ) {
final Component identifier = createEmbeddable(
holder,
new PropertyPreloadedData( null, null, null ),
new PropertyPreloadedData(),
true,
false,
resolveCustomInstantiator( property, returnedClass ),
@ -404,6 +414,7 @@ public class PropertyBinder {
handleOptional( property );
inferOptimisticLocking( property );
LOG.tracev( "Cascading {0} with {1}", name, cascade );
callAttributeBindersInSecondPass( property );
return property;
}
@ -952,11 +963,9 @@ public class PropertyBinder {
rootClass.setVersion( property );
//If version is on a mapped superclass, update the mapping
final org.hibernate.mapping.MappedSuperclass superclass = getMappedSuperclassOrNull(
inferredData.getDeclaringClass(),
inheritanceStatePerClass,
context
);
final XClass declaringClass = inferredData.getDeclaringClass();
final org.hibernate.mapping.MappedSuperclass superclass =
getMappedSuperclassOrNull( declaringClass, inheritanceStatePerClass, context );
if ( superclass != null ) {
superclass.setDeclaredVersion( property );
}
@ -965,16 +974,19 @@ public class PropertyBinder {
rootClass.setDeclaredVersion( property );
}
( (SimpleValue) property.getValue() ).setNullValue( "undefined" );
final SimpleValue simpleValue = (SimpleValue) property.getValue();
simpleValue.setNullValue( "undefined" );
rootClass.setOptimisticLockStyle( OptimisticLockStyle.VERSION );
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Version name: {0}, unsavedValue: {1}", rootClass.getVersion().getName(),
( (SimpleValue) rootClass.getVersion().getValue() ).getNullValue() );
final SimpleValue versionValue = (SimpleValue) rootClass.getVersion().getValue();
LOG.tracev( "Version name: {0}, unsavedValue: {1}",
rootClass.getVersion().getName(),
versionValue.getNullValue() );
}
}
private static void checkVersionProperty(PropertyHolder propertyHolder, boolean isIdentifierMapper) {
if (isIdentifierMapper) {
if ( isIdentifierMapper ) {
throw new AnnotationException( "Class '" + propertyHolder.getEntityName()
+ "' is annotated '@IdClass' and may not have a property annotated '@Version'"
);

View File

@ -25,6 +25,10 @@ public class PropertyPreloadedData implements PropertyData {
this.returnedClass = returnedClass;
}
PropertyPreloadedData() {
this( null, null, null );
}
@Override
public AccessType getDefaultAccess() throws MappingException {
return defaultAccess;

View File

@ -64,7 +64,7 @@ public interface InFlightMetadataCollector extends MetadataImplementor {
BootstrapContext getBootstrapContext();
/**
* Add the PersistentClass for an entity mapping.
* Add the {@link PersistentClass} for an entity mapping.
*
* @param persistentClass The entity metadata
*
@ -74,7 +74,8 @@ public interface InFlightMetadataCollector extends MetadataImplementor {
void addEntityBinding(PersistentClass persistentClass) throws DuplicateMappingException;
/**
* Needed for SecondPass handling
* A map of {@link PersistentClass} by entity name.
* Needed for {@link SecondPass} handling.
*/
Map<String, PersistentClass> getEntityBindingMap();

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
@ -352,8 +351,8 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
return batchSize;
}
public void setBatchSize(int i) {
batchSize = i;
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
public FetchMode getFetchMode() {

View File

@ -463,7 +463,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
* Includes properties defined in superclasses of the mapping inheritance.
* Includes all properties defined as part of a join.
*
* @see #getReferencedProperty for a discussion of "referenceable"
* @see #getReferencedProperty
* @return The referenceable property iterator.
*/
public List<Property> getReferenceableProperties() {

View File

@ -8,8 +8,6 @@ package org.hibernate.mapping;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
@ -36,6 +34,9 @@ import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.hibernate.type.WrapperArrayHandling;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
/**
* A mapping model object representing a property or field of an {@linkplain PersistentClass entity}
* or {@linkplain Component embeddable class}.
@ -56,7 +57,7 @@ public class Property implements Serializable, MetaAttributable {
private boolean lazy;
private String lazyGroup;
private boolean optional;
private java.util.Map metaAttributes;
private java.util.Map<String,MetaAttribute> metaAttributes;
private PersistentClass persistentClass;
private boolean naturalIdentifier;
private boolean isGeneric;
@ -116,7 +117,7 @@ public class Property implements Serializable, MetaAttributable {
}
public void resetUpdateable(boolean updateable) {
setUpdateable(updateable);
setUpdateable( updateable );
boolean[] columnUpdateability = getValue().getColumnUpdateability();
for (int i=0; i<getColumnSpan(); i++ ) {
columnUpdateability[i] = updateable;
@ -124,10 +125,11 @@ public class Property implements Serializable, MetaAttributable {
}
public void resetOptional(boolean optional) {
setOptional(optional);
for ( Selectable column: getValue().getSelectables() ) {
if (column instanceof Column) {
( (Column) column ).setNullable(optional);
setOptional( optional );
for ( Selectable selectable: getValue().getSelectables() ) {
if (selectable instanceof Column) {
final Column column = (Column) selectable;
column.setNullable( optional );
}
}
}
@ -146,7 +148,8 @@ public class Property implements Serializable, MetaAttributable {
return getCompositeCascadeStyle( (CompositeType) type, cascade );
}
else if ( type.isCollectionType() ) {
return getCollectionCascadeStyle( ( (Collection) value ).getElement().getType(), cascade );
final Collection collection = (Collection) value;
return getCollectionCascadeStyle( collection.getElement().getType(), cascade );
}
else {
return getCascadeStyle( cascade );
@ -157,7 +160,7 @@ public class Property implements Serializable, MetaAttributable {
if ( compositeType.isAnyType() ) {
return getCascadeStyle( cascade );
}
int length = compositeType.getSubtypes().length;
final int length = compositeType.getSubtypes().length;
for ( int i=0; i<length; i++ ) {
if ( compositeType.getCascadeStyle(i) != CascadeStyles.NONE ) {
return CascadeStyles.ALL;
@ -167,12 +170,9 @@ public class Property implements Serializable, MetaAttributable {
}
private static CascadeStyle getCollectionCascadeStyle(Type elementType, String cascade) {
if ( elementType.isComponentType() ) {
return getCompositeCascadeStyle( (CompositeType) elementType, cascade );
}
else {
return getCascadeStyle( cascade );
}
return elementType.isComponentType()
? getCompositeCascadeStyle( (CompositeType) elementType, cascade )
: getCascadeStyle( cascade );
}
private static CascadeStyle getCascadeStyle(String cascade) {
@ -180,8 +180,8 @@ public class Property implements Serializable, MetaAttributable {
return CascadeStyles.NONE;
}
else {
StringTokenizer tokens = new StringTokenizer(cascade, ", ");
CascadeStyle[] styles = new CascadeStyle[ tokens.countTokens() ] ;
final StringTokenizer tokens = new StringTokenizer(cascade, ", ");
final CascadeStyle[] styles = new CascadeStyle[ tokens.countTokens() ] ;
int i=0;
while ( tokens.hasMoreTokens() ) {
styles[i++] = CascadeStyles.getCascadeStyle( tokens.nextToken() );
@ -254,7 +254,9 @@ public class Property implements Serializable, MetaAttributable {
/**
* Approximate!
* @deprecated this method is no longer used
*/
@Deprecated(since = "6", forRemoval = true)
boolean isNullable() {
return value==null || value.isNullable();
}
@ -268,7 +270,7 @@ public class Property implements Serializable, MetaAttributable {
}
public MetaAttribute getMetaAttribute(String attributeName) {
return metaAttributes==null?null:(MetaAttribute) metaAttributes.get(attributeName);
return metaAttributes==null ? null : metaAttributes.get(attributeName);
}
public void setMetaAttributes(Map<String, MetaAttribute> metas) {
@ -369,21 +371,28 @@ public class Property implements Serializable, MetaAttributable {
this.selectable = selectable;
}
/**
* @deprecated this method is no longer used
*/
@Deprecated(since = "6", forRemoval = true)
public String getAccessorPropertyName(RepresentationMode mode) {
return getName();
}
// todo : remove
@Internal
public Getter getGetter(Class clazz) throws MappingException {
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getGetter();
}
// todo : remove
@Internal
public Setter getSetter(Class clazz) throws MappingException {
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getSetter();
}
// todo : remove
@Internal
public PropertyAccessStrategy getPropertyAccessStrategy(Class clazz) throws MappingException {
final PropertyAccessStrategy propertyAccessStrategy = getPropertyAccessStrategy();
if ( propertyAccessStrategy != null ) {
@ -403,11 +412,12 @@ public class Property implements Serializable, MetaAttributable {
? RepresentationMode.MAP
: RepresentationMode.POJO;
return resolveServiceRegistry().requireService( PropertyAccessStrategyResolver.class )
return resolveServiceRegistry()
.requireService( PropertyAccessStrategyResolver.class )
.resolvePropertyAccessStrategy( clazz, accessName, representationMode );
}
protected ServiceRegistry resolveServiceRegistry() {
ServiceRegistry resolveServiceRegistry() {
if ( getPersistentClass() != null ) {
return getPersistentClass().getServiceRegistry();
}
@ -442,20 +452,16 @@ public class Property implements Serializable, MetaAttributable {
}
public void addCallbackDefinitions(java.util.List<CallbackDefinition> callbackDefinitions) {
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
return;
if ( callbackDefinitions != null && !callbackDefinitions.isEmpty() ) {
if ( this.callbackDefinitions == null ) {
this.callbackDefinitions = new ArrayList<>();
}
this.callbackDefinitions.addAll( callbackDefinitions );
}
if ( this.callbackDefinitions == null ) {
this.callbackDefinitions = new ArrayList<>();
}
this.callbackDefinitions.addAll( callbackDefinitions );
}
public java.util.List<CallbackDefinition> getCallbackDefinitions() {
if ( callbackDefinitions == null ) {
return Collections.emptyList();
}
return Collections.unmodifiableList( callbackDefinitions );
return callbackDefinitions == null ? emptyList() : unmodifiableList( callbackDefinitions );
}
public String getReturnedClassName() {

View File

@ -41,7 +41,6 @@ import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@ -602,18 +601,21 @@ public class EntityMetamodel implements Serializable {
private static boolean indicatesOwnedCollection(Type type, MetadataImplementor metadata) {
if ( type.isCollectionType() ) {
String role = ( (CollectionType) type ).getRole();
return !metadata.getCollectionBinding( role ).isInverse();
final CollectionType collectionType = (CollectionType) type;
return !metadata.getCollectionBinding( collectionType.getRole() ).isInverse();
}
else if ( type.isComponentType() ) {
Type[] subtypes = ( (CompositeType) type ).getSubtypes();
for ( Type subtype : subtypes ) {
final CompositeType compositeType = (CompositeType) type;
for ( Type subtype : compositeType.getSubtypes() ) {
if ( indicatesOwnedCollection( subtype, metadata ) ) {
return true;
}
}
return false;
}
else {
return false;
}
return false;
}
public SessionFactoryImplementor getSessionFactory() {
@ -676,9 +678,6 @@ public class EntityMetamodel implements Serializable {
return propertyIndexes.get( propertyName );
}
public boolean hasCollections() {
return hasCollections;
}

View File

@ -19,7 +19,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

View File

@ -153,7 +153,6 @@ public class DepthOneBatchTest {
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "AGENCY_ID")
@BatchSize(size = 2)
public AgencyDetail getAgencyDetail() {
return agencyDetail;
}