HHH-15959 add TypeBinders + fix multiple AttributeBinders on a single field
This commit is contained in:
parent
e48a8120a9
commit
df5980226c
|
@ -24,6 +24,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
* will be called when the annotation is discovered by Hibernate.
|
* will be called when the annotation is discovered by Hibernate.
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
*
|
||||||
|
* @see TypeBinderType
|
||||||
*/
|
*/
|
||||||
@Target(ANNOTATION_TYPE)
|
@Target(ANNOTATION_TYPE)
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.annotations;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.binder.TypeBinder;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates a user-defined annotation with a {@link TypeBinder},
|
||||||
|
* allowing the annotation to drive some custom model binding.
|
||||||
|
* <p>
|
||||||
|
* The user-defined annotation may be used to annotate entity and
|
||||||
|
* embeddable classes. The {@code TypeBinder} will be called when
|
||||||
|
* the annotation is discovered by Hibernate.
|
||||||
|
*
|
||||||
|
* @author Gavin King
|
||||||
|
*
|
||||||
|
* @see AttributeBinderType
|
||||||
|
*/
|
||||||
|
@Target(ANNOTATION_TYPE)
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Incubating
|
||||||
|
public @interface TypeBinderType {
|
||||||
|
/**
|
||||||
|
* @return a type which implements {@link TypeBinder}
|
||||||
|
*/
|
||||||
|
Class<? extends TypeBinder<?>> binder();
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
import org.hibernate.mapping.Component;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows a user-written annotation to drive some customized model binding.
|
||||||
|
* <p>
|
||||||
|
* An implementation of this interface interacts directly with model objects
|
||||||
|
* like {@link PersistentClass} and {@link Component} to implement the
|
||||||
|
* semantics of some {@link org.hibernate.annotations.TypeBinderType
|
||||||
|
* custom mapping annotation}.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.annotations.TypeBinderType
|
||||||
|
*
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
public interface TypeBinder<A extends Annotation> {
|
||||||
|
/**
|
||||||
|
* Perform some custom configuration of the model relating to the given annotated
|
||||||
|
* {@link PersistentClass entity class}.
|
||||||
|
*
|
||||||
|
* @param annotation an annotation of the entity class that is declared as an
|
||||||
|
* {@link org.hibernate.annotations.TypeBinderType}
|
||||||
|
* @param persistentClass the entity class
|
||||||
|
*/
|
||||||
|
void bind(A annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass);
|
||||||
|
/**
|
||||||
|
* Perform some custom configuration of the model relating to the given annotated
|
||||||
|
* {@link Component embeddable class}.
|
||||||
|
*
|
||||||
|
* @param annotation an annotation of the embeddable class that is declared as an
|
||||||
|
* {@link org.hibernate.annotations.TypeBinderType}
|
||||||
|
* @param embeddableClass the embeddable class
|
||||||
|
*/
|
||||||
|
void bind(A annotation, MetadataBuildingContext buildingContext, Component embeddableClass);
|
||||||
|
}
|
|
@ -37,6 +37,5 @@ public class AttributeAccessorBinder implements AttributeBinder<AttributeAccesso
|
||||||
else {
|
else {
|
||||||
throw new AnnotationException("'@AttributeAccessor' annotation must specify a 'strategy'");
|
throw new AnnotationException("'@AttributeAccessor' annotation must specify a 'strategy'");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Built-in implementations of {@link org.hibernate.binder.AttributeBinder}.
|
* Built-in implementations of {@link org.hibernate.binder.AttributeBinder}
|
||||||
|
* and {@link org.hibernate.binder.TypeBinder}.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.binder.internal;
|
package org.hibernate.binder.internal;
|
||||||
|
|
|
@ -6,13 +6,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This package defines an easy way to extend Hibernate with
|
* This package defines an easy way to extend Hibernate with user-defined
|
||||||
* user-defined annotations that define customized O/R mappings
|
* annotations that define customized O/R mappings of annotated entities
|
||||||
* of annotated entity attributes.
|
* and annotated entity attributes.
|
||||||
* <p>
|
* <ul>
|
||||||
* The meta-annotation
|
* <li>The meta-annotation
|
||||||
* {@link org.hibernate.annotations.AttributeBinderType}
|
* {@link org.hibernate.annotations.TypeBinderType @TypeBinderType}
|
||||||
* associates an {@link org.hibernate.binder.AttributeBinder}
|
* associates a {@link org.hibernate.binder.TypeBinder} with a
|
||||||
* with a user-written annotation.
|
* user-written annotation which targets entity and embeddable
|
||||||
|
* {@linkplain java.lang.annotation.ElementType#TYPE types}.
|
||||||
|
* <li>The meta-annotation
|
||||||
|
* {@link org.hibernate.annotations.AttributeBinderType @AttributeBinderType}
|
||||||
|
* associates an {@link org.hibernate.binder.AttributeBinder}
|
||||||
|
* with a user-written annotation which targets
|
||||||
|
* {@linkplain java.lang.annotation.ElementType#FIELD fields} and
|
||||||
|
* properties of entity types and embeddable classes.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.binder.AttributeBinder
|
||||||
|
* @see org.hibernate.binder.TypeBinder
|
||||||
*/
|
*/
|
||||||
package org.hibernate.binder;
|
package org.hibernate.binder;
|
||||||
|
|
|
@ -19,10 +19,12 @@ import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.annotations.Instantiator;
|
import org.hibernate.annotations.Instantiator;
|
||||||
|
import org.hibernate.annotations.TypeBinderType;
|
||||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XMethod;
|
import org.hibernate.annotations.common.reflection.XMethod;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
|
import org.hibernate.binder.TypeBinder;
|
||||||
import org.hibernate.boot.spi.AccessType;
|
import org.hibernate.boot.spi.AccessType;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.boot.spi.PropertyData;
|
import org.hibernate.boot.spi.PropertyData;
|
||||||
|
@ -37,6 +39,7 @@ import org.hibernate.property.access.spi.PropertyAccessStrategy;
|
||||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -45,6 +48,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
|
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
|
||||||
|
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
||||||
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
|
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
|
||||||
|
@ -109,22 +113,31 @@ public class EmbeddableBinder {
|
||||||
actualColumns = null;
|
actualColumns = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindEmbeddable(
|
return createEmbeddedProperty(
|
||||||
inferredData,
|
inferredData,
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
entityBinder.getPropertyAccessor( property ),
|
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
|
||||||
context,
|
context,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
propertyBinder.isId(),
|
propertyBinder.isId(),
|
||||||
inheritanceStatePerClass,
|
inheritanceStatePerClass,
|
||||||
referencedEntityName,
|
bindEmbeddable(
|
||||||
propertyName,
|
inferredData,
|
||||||
determineCustomInstantiator( property, returnedClass, context ),
|
propertyHolder,
|
||||||
compositeUserType,
|
entityBinder.getPropertyAccessor( property ),
|
||||||
actualColumns,
|
entityBinder,
|
||||||
columns
|
isIdentifierMapper,
|
||||||
|
context,
|
||||||
|
isComponentEmbedded,
|
||||||
|
propertyBinder.isId(),
|
||||||
|
inheritanceStatePerClass,
|
||||||
|
referencedEntityName,
|
||||||
|
propertyName,
|
||||||
|
determineCustomInstantiator( property, returnedClass, context ),
|
||||||
|
compositeUserType,
|
||||||
|
actualColumns,
|
||||||
|
columns
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +147,7 @@ public class EmbeddableBinder {
|
||||||
|| returnedClass.isAnnotationPresent( Embeddable.class );
|
|| returnedClass.isAnnotationPresent( Embeddable.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropertyBinder bindEmbeddable(
|
private static Component bindEmbeddable(
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
AccessType propertyAccessor,
|
AccessType propertyAccessor,
|
||||||
|
@ -189,18 +202,44 @@ public class EmbeddableBinder {
|
||||||
component.setKey( true );
|
component.setKey( true );
|
||||||
checkEmbeddedId( inferredData, propertyHolder, referencedEntityName, component );
|
checkEmbeddedId( inferredData, propertyHolder, referencedEntityName, component );
|
||||||
}
|
}
|
||||||
|
callTypeBinders( component, context, inferredData.getPropertyClass() );
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void callTypeBinders(Component component, MetadataBuildingContext context, XClass annotatedClass ) {
|
||||||
|
for ( Annotation containingAnnotation : findContainingAnnotations( annotatedClass, TypeBinderType.class) ) {
|
||||||
|
final TypeBinderType binderType = containingAnnotation.annotationType().getAnnotation( TypeBinderType.class );
|
||||||
|
try {
|
||||||
|
final TypeBinder binder = binderType.binder().newInstance();
|
||||||
|
binder.bind( containingAnnotation, context, component );
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
throw new AnnotationException( "error processing @TypeBinderType annotation '" + containingAnnotation + "'", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PropertyBinder createEmbeddedProperty(
|
||||||
|
PropertyData inferredData,
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
EntityBinder entityBinder,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
boolean isComponentEmbedded,
|
||||||
|
boolean isId,
|
||||||
|
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||||
|
Component component) {
|
||||||
final PropertyBinder binder = new PropertyBinder();
|
final PropertyBinder binder = new PropertyBinder();
|
||||||
binder.setDeclaringClass( inferredData.getDeclaringClass() );
|
binder.setDeclaringClass( inferredData.getDeclaringClass() );
|
||||||
binder.setName( inferredData.getPropertyName() );
|
binder.setName( inferredData.getPropertyName() );
|
||||||
binder.setValue( component );
|
binder.setValue(component);
|
||||||
binder.setProperty( inferredData.getProperty() );
|
binder.setProperty( inferredData.getProperty() );
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
binder.setEmbedded( isComponentEmbedded );
|
binder.setEmbedded(isComponentEmbedded);
|
||||||
binder.setHolder( propertyHolder );
|
binder.setHolder(propertyHolder);
|
||||||
binder.setId( isId );
|
binder.setId(isId);
|
||||||
binder.setEntityBinder( entityBinder );
|
binder.setEntityBinder(entityBinder);
|
||||||
binder.setInheritanceStatePerClass( inheritanceStatePerClass );
|
binder.setInheritanceStatePerClass(inheritanceStatePerClass);
|
||||||
binder.setBuildingContext( context );
|
binder.setBuildingContext(context);
|
||||||
binder.makePropertyAndBind();
|
binder.makePropertyAndBind();
|
||||||
return binder;
|
return binder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,12 @@ import org.hibernate.annotations.SelectBeforeUpdate;
|
||||||
import org.hibernate.annotations.Subselect;
|
import org.hibernate.annotations.Subselect;
|
||||||
import org.hibernate.annotations.Synchronize;
|
import org.hibernate.annotations.Synchronize;
|
||||||
import org.hibernate.annotations.Tables;
|
import org.hibernate.annotations.Tables;
|
||||||
|
import org.hibernate.annotations.TypeBinderType;
|
||||||
import org.hibernate.annotations.Where;
|
import org.hibernate.annotations.Where;
|
||||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
|
import org.hibernate.binder.TypeBinder;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
import org.hibernate.boot.model.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.boot.model.internal.InheritanceState.ElementsToProcess;
|
import org.hibernate.boot.model.internal.InheritanceState.ElementsToProcess;
|
||||||
|
@ -131,6 +133,7 @@ import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.toAliasEntityMap;
|
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.BinderHelper.toAliasTableMap;
|
||||||
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
|
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
|
||||||
|
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
|
||||||
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
|
||||||
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
|
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
|
||||||
|
@ -233,6 +236,20 @@ public class EntityBinder {
|
||||||
// comment, checkConstraint, and indexes are processed here
|
// comment, checkConstraint, and indexes are processed here
|
||||||
entityBinder.processComplementaryTableDefinitions();
|
entityBinder.processComplementaryTableDefinitions();
|
||||||
bindCallbacks( clazzToProcess, persistentClass, context );
|
bindCallbacks( clazzToProcess, persistentClass, context );
|
||||||
|
entityBinder.callTypeBinders( persistentClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void callTypeBinders(PersistentClass persistentClass) {
|
||||||
|
for ( Annotation containingAnnotation : findContainingAnnotations( annotatedClass, TypeBinderType.class ) ) {
|
||||||
|
final TypeBinderType binderType = containingAnnotation.annotationType().getAnnotation( TypeBinderType.class );
|
||||||
|
try {
|
||||||
|
final TypeBinder binder = binderType.binder().newInstance();
|
||||||
|
binder.bind( containingAnnotation, context, persistentClass );
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
throw new AnnotationException( "error processing @TypeBinderType annotation '" + containingAnnotation + "'", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleIdentifier(
|
private void handleIdentifier(
|
||||||
|
|
|
@ -9,6 +9,8 @@ package org.hibernate.boot.model.internal;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
|
@ -156,21 +158,20 @@ public final class HCANNHelper {
|
||||||
*
|
*
|
||||||
* @implNote Searches only one level deep
|
* @implNote Searches only one level deep
|
||||||
*/
|
*/
|
||||||
public static <A extends Annotation, T extends Annotation> A findContainingAnnotation(
|
public static List<Annotation> findContainingAnnotations(
|
||||||
XAnnotatedElement annotatedElement,
|
XAnnotatedElement annotatedElement,
|
||||||
Class<T> annotationType) {
|
Class<? extends Annotation> annotationType) {
|
||||||
|
|
||||||
|
final List<Annotation> result = new ArrayList<>();
|
||||||
|
|
||||||
final Annotation[] annotations = annotatedElement.getAnnotations();
|
final Annotation[] annotations = annotatedElement.getAnnotations();
|
||||||
for ( Annotation annotation : annotations ) {
|
for ( Annotation annotation : annotations ) {
|
||||||
// annotation = @Sequence
|
final Annotation metaAnn = annotation.annotationType().getAnnotation( annotationType );
|
||||||
|
|
||||||
final T metaAnn = annotation.annotationType().getAnnotation( annotationType );
|
|
||||||
if ( metaAnn != null ) {
|
if ( metaAnn != null ) {
|
||||||
//noinspection unchecked
|
result.add( annotation );
|
||||||
return (A) annotation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,11 +84,12 @@ import static org.hibernate.boot.model.internal.EmbeddableBinder.createComposite
|
||||||
import static org.hibernate.boot.model.internal.EmbeddableBinder.createEmbeddable;
|
import static org.hibernate.boot.model.internal.EmbeddableBinder.createEmbeddable;
|
||||||
import static org.hibernate.boot.model.internal.EmbeddableBinder.isEmbedded;
|
import static org.hibernate.boot.model.internal.EmbeddableBinder.isEmbedded;
|
||||||
import static org.hibernate.boot.model.internal.HCANNHelper.findAnnotation;
|
import static org.hibernate.boot.model.internal.HCANNHelper.findAnnotation;
|
||||||
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotation;
|
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
|
||||||
import static org.hibernate.boot.model.internal.TimeZoneStorageHelper.resolveTimeZoneStorageCompositeUserType;
|
import static org.hibernate.boot.model.internal.TimeZoneStorageHelper.resolveTimeZoneStorageCompositeUserType;
|
||||||
import static org.hibernate.boot.model.internal.ToOneBinder.bindManyToOne;
|
import static org.hibernate.boot.model.internal.ToOneBinder.bindManyToOne;
|
||||||
import static org.hibernate.boot.model.internal.ToOneBinder.bindOneToOne;
|
import static org.hibernate.boot.model.internal.ToOneBinder.bindOneToOne;
|
||||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.combine;
|
||||||
import static org.hibernate.mapping.Constraint.hashedName;
|
import static org.hibernate.mapping.Constraint.hashedName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,15 +270,14 @@ public class PropertyBinder {
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
private void callAttributeBinders(Property prop) {
|
private void callAttributeBinders(Property prop) {
|
||||||
final Annotation containingAnnotation = findContainingAnnotation( property, AttributeBinderType.class);
|
for ( Annotation containingAnnotation : findContainingAnnotations(property, AttributeBinderType.class ) ) {
|
||||||
if ( containingAnnotation != null ) {
|
|
||||||
final AttributeBinderType binderType = containingAnnotation.annotationType().getAnnotation( AttributeBinderType.class );
|
final AttributeBinderType binderType = containingAnnotation.annotationType().getAnnotation( AttributeBinderType.class );
|
||||||
try {
|
try {
|
||||||
final AttributeBinder binder = binderType.binder().newInstance();
|
final AttributeBinder binder = binderType.binder().newInstance();
|
||||||
binder.bind( containingAnnotation, buildingContext, entityBinder.getPersistentClass(), prop );
|
binder.bind( containingAnnotation, buildingContext, entityBinder.getPersistentClass(), prop );
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch ( Exception e ) {
|
||||||
throw new AnnotationException( "error processing @AttributeBinderType annotation", e );
|
throw new AnnotationException( "error processing @AttributeBinderType annotation '" + containingAnnotation + "'", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1270,16 +1270,21 @@ public class PropertyBinder {
|
||||||
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
+ "' belongs to an '@IdClass' and may not be annotated '@Id' or '@EmbeddedId'" );
|
||||||
}
|
}
|
||||||
final XProperty idProperty = inferredData.getProperty();
|
final XProperty idProperty = inferredData.getProperty();
|
||||||
final Annotation idGeneratorAnnotation = findContainingAnnotation( idProperty, IdGeneratorType.class );
|
final List<Annotation> idGeneratorAnnotations = findContainingAnnotations( idProperty, IdGeneratorType.class );
|
||||||
final Annotation generatorAnnotation = findContainingAnnotation( idProperty, ValueGenerationType.class );
|
final List<Annotation> generatorAnnotations = findContainingAnnotations( idProperty, ValueGenerationType.class );
|
||||||
//TODO: validate that we don't have too many generator annotations and throw
|
generatorAnnotations.removeAll( idGeneratorAnnotations );
|
||||||
if ( idGeneratorAnnotation != null ) {
|
if ( idGeneratorAnnotations.size() + generatorAnnotations.size() > 1 ) {
|
||||||
idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( idProperty, idGeneratorAnnotation ) );
|
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
||||||
|
+ "' has too many generator annotations " + combine( idGeneratorAnnotations, generatorAnnotations ) );
|
||||||
}
|
}
|
||||||
else if ( generatorAnnotation != null ) {
|
if ( !idGeneratorAnnotations.isEmpty() ) {
|
||||||
|
idValue.setCustomIdGeneratorCreator( identifierGeneratorCreator( idProperty, idGeneratorAnnotations.get(0) ) );
|
||||||
|
}
|
||||||
|
else if ( !generatorAnnotations.isEmpty() ) {
|
||||||
// idValue.setCustomGeneratorCreator( generatorCreator( idProperty, generatorAnnotation ) );
|
// idValue.setCustomGeneratorCreator( generatorCreator( idProperty, generatorAnnotation ) );
|
||||||
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
throw new AnnotationException( "Property '"+ getPath( propertyHolder, inferredData )
|
||||||
+ "' is annotated '" + generatorAnnotation.annotationType() + "' which is not an '@IdGeneratorType'" );
|
+ "' is annotated '" + generatorAnnotations.get(0).annotationType()
|
||||||
|
+ "' which is not an '@IdGeneratorType'" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final XClass entityClass = inferredData.getClassOrElement();
|
final XClass entityClass = inferredData.getClassOrElement();
|
||||||
|
|
|
@ -51,9 +51,9 @@ import static org.hibernate.id.IdentifierGeneratorHelper.POST_INSERT_INDICATOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping model object that represents an {@linkplain jakarta.persistence.Embeddable embeddable class}.
|
* A mapping model object that represents an {@linkplain jakarta.persistence.Embeddable embeddable class}.
|
||||||
* <p>
|
*
|
||||||
* Note that the name of this class is historical and unfortunate. An embeddable class holds a "component"
|
* @apiNote The name of this class is historical and unfortunate. An embeddable class holds a "component"
|
||||||
* of the state of an entity. It has absolutely nothing to do with modularity in software engineering.
|
* of the state of an entity. It has absolutely nothing to do with modularity in software engineering.
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class Table implements Serializable, ContributableDatabaseObject {
|
||||||
|
|
||||||
private List<Function<SqlStringGenerationContext, InitCommand>> initCommandProducers;
|
private List<Function<SqlStringGenerationContext, InitCommand>> initCommandProducers;
|
||||||
|
|
||||||
@Deprecated(since="6.2") @Remove
|
@Deprecated(since="6.2", forRemoval = true)
|
||||||
public Table() {
|
public Table() {
|
||||||
this( "orm" );
|
this( "orm" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,10 @@
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{@link org.hibernate.context.spi} defines support for context-bound "current" sessions
|
{@link org.hibernate.context.spi} defines support for context-bound "current" sessions
|
||||||
and contextual multi-tenancy,
|
and contextual multi-tenancy, and
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{@link org.hibernate.binder} allows for user-defined mapping annotations.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -133,7 +133,10 @@
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{@link org.hibernate.context.spi} defines support for context-bound "current" sessions
|
{@link org.hibernate.context.spi} defines support for context-bound "current" sessions
|
||||||
and contextual multi-tenancy,
|
and contextual multi-tenancy, and
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{@link org.hibernate.binder} allows for user-defined mapping annotations.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
|
|
Loading…
Reference in New Issue