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:
parent
4a70a23212
commit
95ee026cb2
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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'");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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'"
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue