diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/Binders.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/Binders.java
new file mode 100644
index 000000000000..8b17dbbed4db
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/Binders.java
@@ -0,0 +1,112 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.boot.model.internal;
+
+import org.hibernate.AnnotationException;
+import org.hibernate.annotations.AttributeBinderType;
+import org.hibernate.annotations.TypeBinderType;
+import org.hibernate.binder.AttributeBinder;
+import org.hibernate.binder.TypeBinder;
+import org.hibernate.boot.spi.MetadataBuildingContext;
+import org.hibernate.mapping.Component;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+
+import java.lang.annotation.Annotation;
+
+import static org.hibernate.internal.util.GenericsHelper.typeArguments;
+
+/**
+ * @author Gavin King
+ * @since 7.3
+ */
+public class Binders {
+ static void callTypeBinder(
+ Annotation annotation, Class annotationType,
+ Component embeddable,
+ MetadataBuildingContext context) {
+ try {
+ typeBinder( annotationType )
+ .bind( annotationType.cast( annotation ),
+ context, embeddable );
+ }
+ catch (Exception e) {
+ throw new AnnotationException(
+ "Error processing @TypeBinderType annotation '%s' for embeddable type '%s'"
+ .formatted( annotation, embeddable.getComponentClassName() ), e );
+ }
+ }
+
+ static void callTypeBinder(
+ Annotation annotation, Class annotationType,
+ PersistentClass entity,
+ MetadataBuildingContext context) {
+ try {
+ typeBinder( annotationType )
+ .bind( annotationType.cast( annotation ),
+ context, entity );
+ }
+ catch (Exception e) {
+ throw new AnnotationException(
+ "Error processing @TypeBinderType annotation '%s' for entity type '%s'"
+ .formatted( annotation, entity.getClassName() ), e );
+ }
+ }
+
+ static void callPropertyBinder(
+ Annotation annotation, Class annotationType,
+ PersistentClass entity, Property property,
+ MetadataBuildingContext context) {
+ try {
+ propertyBinder( annotationType )
+ .bind( annotationType.cast( annotation ),
+ context, entity, property );
+ }
+ catch (Exception e) {
+ throw new AnnotationException(
+ "error processing @AttributeBinderType annotation '%s' for attribute '%s' of entity type '%s'"
+ .formatted( annotation, property.getName(), entity.getClassName() ), e );
+ }
+ }
+
+ private static TypeBinder typeBinder(Class annotationType)
+ throws Exception {
+ final var binderType =
+ annotationType.getAnnotation( TypeBinderType.class )
+ .binder();
+ checkImplementedTypeArgument( annotationType, binderType, TypeBinder.class );
+ @SuppressWarnings("unchecked") // Safe, we just checked
+ final var castBinderType = (Class extends TypeBinder>) binderType;
+ return castBinderType.getDeclaredConstructor().newInstance();
+ }
+
+ private static AttributeBinder propertyBinder(Class annotationType)
+ throws Exception {
+ final var binderType =
+ annotationType.getAnnotation( AttributeBinderType.class )
+ .binder();
+ checkImplementedTypeArgument( annotationType, binderType, PropertyBinder.class );
+ @SuppressWarnings("unchecked") // Safe, we just checked
+ final var castBinderType = (Class extends AttributeBinder>) binderType;
+ return castBinderType.getDeclaredConstructor().newInstance();
+ }
+
+ private static void checkImplementedTypeArgument(
+ Class extends Annotation> annotationType,
+ Class> binderType, Class> implementedType) {
+ final var args = typeArguments( implementedType, binderType );
+ if ( args.length == 1 ) {
+ final var requiredAnnotationType = args[0];
+ if ( annotationType != requiredAnnotationType ) {
+ throw new AnnotationException(
+ "Wrong kind of binder for annotation type:"
+ + " '%s' does not accept an annotation of type '%s'"
+ .formatted( binderType.getTypeName(),
+ annotationType.getTypeName() )
+ );
+ }
+ }
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java
index 030253640cf6..9ddc33ae4af0 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EmbeddableBinder.java
@@ -25,7 +25,6 @@
import org.hibernate.annotations.EmbeddedColumnNaming;
import org.hibernate.annotations.Instantiator;
import org.hibernate.annotations.TypeBinderType;
-import org.hibernate.binder.TypeBinder;
import org.hibernate.boot.spi.AccessType;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData;
@@ -65,6 +64,7 @@
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath;
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
+import static org.hibernate.boot.model.internal.Binders.callTypeBinder;
import static org.hibernate.boot.model.internal.ComponentPropertyHolder.applyExplicitTableName;
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
import static org.hibernate.boot.model.internal.GeneratorBinder.createIdGeneratorsFromGeneratorAnnotations;
@@ -316,17 +316,7 @@ private static void callTypeBinders(Component embeddable, MetadataBuildingContex
.getMetaAnnotated( TypeBinderType.class,
context.getBootstrapContext().getModelsContext() );
for ( var metaAnnotated : metaAnnotatedAnnotations ) {
- final var binderType = metaAnnotated.annotationType().getAnnotation( TypeBinderType.class );
- try {
- //noinspection rawtypes
- final TypeBinder binder = binderType.binder().getDeclaredConstructor().newInstance();
- //noinspection unchecked
- binder.bind( metaAnnotated, context, embeddable );
- }
- catch (Exception e) {
- throw new AnnotationException(
- "error processing @TypeBinderType annotation '" + metaAnnotated + "'", e );
- }
+ callTypeBinder( metaAnnotated, metaAnnotated.annotationType(), embeddable, context );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java
index b0e9332eaeb8..034e931d80ff 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java
@@ -63,7 +63,6 @@
import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.TypeBinderType;
import org.hibernate.annotations.View;
-import org.hibernate.binder.TypeBinder;
import org.hibernate.boot.model.NamedEntityGraphDefinition;
import org.hibernate.boot.model.internal.InheritanceState.ElementsToProcess;
import org.hibernate.boot.model.naming.EntityNaming;
@@ -134,6 +133,7 @@
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
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.Binders.callTypeBinder;
import static org.hibernate.boot.model.internal.ClassPropertyHolder.setType;
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverridableAnnotation;
import static org.hibernate.boot.model.internal.DialectOverridesAnnotationHelper.getOverrideAnnotation;
@@ -383,23 +383,7 @@ private void addCheckToEntity(Check check) {
private void callTypeBinders(PersistentClass persistentClass) {
for ( var metaAnnotated : annotatedClass.getMetaAnnotated( TypeBinderType.class, modelsContext() ) ) {
- applyTypeBinder( metaAnnotated, persistentClass );
- }
- }
-
- private void applyTypeBinder(Annotation containingAnnotation, PersistentClass persistentClass) {
- final var binderClass =
- containingAnnotation.annotationType()
- .getAnnotation( TypeBinderType.class )
- .binder();
- try {
- //noinspection rawtypes
- final TypeBinder binder = binderClass.getConstructor().newInstance();
- //noinspection unchecked
- binder.bind( containingAnnotation, context, persistentClass );
- }
- catch ( Exception e ) {
- throw new AnnotationException( "error processing @TypeBinderType annotation '" + containingAnnotation + "'", e );
+ callTypeBinder( metaAnnotated, metaAnnotated.annotationType(), persistentClass, context );
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java
index dc3084f43870..77d1f9f1e9e6 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java
@@ -41,7 +41,6 @@
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.OptimisticLock;
import org.hibernate.annotations.Parent;
-import org.hibernate.binder.AttributeBinder;
import org.hibernate.boot.spi.AccessType;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.PropertyData;
@@ -81,6 +80,7 @@
import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclassOrNull;
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
+import static org.hibernate.boot.model.internal.Binders.callPropertyBinder;
import static org.hibernate.boot.model.internal.ClassPropertyHolder.handleGenericComponentProperty;
import static org.hibernate.boot.model.internal.ClassPropertyHolder.prepareActualProperty;
import static org.hibernate.boot.model.internal.CollectionBinder.bindCollection;
@@ -303,30 +303,16 @@ private boolean autoApplyConverters() {
&& !memberDetails.hasDirectAnnotationUsage( Temporal.class );
}
- @SuppressWarnings({"rawtypes", "unchecked"})
private void callAttributeBinders(Property property, Map persistentClasses) {
final var metaAnnotatedTargets =
memberDetails.getMetaAnnotated( AttributeBinderType.class, getSourceModelContext() );
- final var descriptorRegistry = getSourceModelContext().getAnnotationDescriptorRegistry();
- for ( int i = 0; i < metaAnnotatedTargets.size(); i++ ) {
- final Annotation metaAnnotatedTarget = metaAnnotatedTargets.get( i );
- final var metaAnnotatedDescriptor =
- descriptorRegistry.getDescriptor( metaAnnotatedTarget.annotationType() );
- final var binderTypeAnn =
- metaAnnotatedDescriptor.getDirectAnnotationUsage( AttributeBinderType.class );
- try {
- final AttributeBinder binder = binderTypeAnn.binder().getConstructor().newInstance();
- final var persistentClass =
- entityBinder != null
- ? entityBinder.getPersistentClass()
- : persistentClasses.get( holder.getEntityName() );
- binder.bind( metaAnnotatedTarget, buildingContext, persistentClass, property );
- }
- catch ( Exception e ) {
- throw new AnnotationException( "error processing @AttributeBinderType annotation '"
- + metaAnnotatedDescriptor.getAnnotationType().getName() + "' for property '"
- + qualify( holder.getPath(), name ) + "'", e );
- }
+ for ( final var metaAnnotatedTarget : metaAnnotatedTargets ) {
+ final var annotationType = metaAnnotatedTarget.annotationType();
+ final var persistentClass =
+ entityBinder != null
+ ? entityBinder.getPersistentClass()
+ : persistentClasses.get( holder.getEntityName() );
+ callPropertyBinder( metaAnnotatedTarget, annotationType, persistentClass, property, buildingContext );
}
}