diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/AttributeProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/AttributeProcessor.java index d4cbb7b..bfa0406 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/AttributeProcessor.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/AttributeProcessor.java @@ -256,18 +256,8 @@ public static MutableMemberDetails processBasicIdAttribute( sourceModelBuildingContext ); - XmlAnnotationHelper.applyUserType( - jaxbId.getType(), - memberDetails, - sourceModelBuildingContext - ); - XmlAnnotationHelper.applyTargetClass( - jaxbId.getTargetClass(), - memberDetails, - sourceModelBuildingContext - ); - XmlAnnotationHelper.applyJdbcType( - jaxbId.getJdbcType(), + XmlAnnotationHelper.applyBasicTypeComposition( + jaxbId, memberDetails, sourceModelBuildingContext ); @@ -359,9 +349,7 @@ public static MutableMemberDetails processBasicAttribute( XmlAnnotationHelper.applyConvert( jaxbBasic.getConvert(), memberDetails, sourceModelBuildingContext ); - XmlAnnotationHelper.applyUserType( jaxbBasic.getType(), memberDetails, sourceModelBuildingContext ); - XmlAnnotationHelper.applyTargetClass( jaxbBasic.getTargetClass(), memberDetails, sourceModelBuildingContext ); - XmlAnnotationHelper.applyJdbcType( jaxbBasic.getJdbcType(), memberDetails, sourceModelBuildingContext ); + XmlAnnotationHelper.applyBasicTypeComposition( jaxbBasic, memberDetails, sourceModelBuildingContext ); XmlAnnotationHelper.applyTemporal( jaxbBasic.getTemporal(), memberDetails, sourceModelBuildingContext ); XmlAnnotationHelper.applyLob( jaxbBasic.getLob(), memberDetails, sourceModelBuildingContext ); XmlAnnotationHelper.applyEnumerated( jaxbBasic.getEnumerated(), memberDetails, sourceModelBuildingContext ); diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java index 192b7dc..39134cb 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java @@ -304,46 +304,51 @@ private static ClassDetails determineDynamicAttributeJavaType( if ( jaxbPersistentAttribute instanceof JaxbIdImpl ) { final JaxbIdImpl jaxbId = (JaxbIdImpl) jaxbPersistentAttribute; - if ( jaxbId.getJavaType() == null || jaxbId.getJavaType().getClazz() == null ) { - return null; - } - else { - return XmlAnnotationHelper.resolveJavaType( - jaxbId.getJavaType().getClazz(), - sourceModelBuildingContext - ); - } + return XmlAnnotationHelper.resolveJavaType( jaxbId.getTarget(), sourceModelBuildingContext ); } if ( jaxbPersistentAttribute instanceof JaxbEmbeddedIdImpl ) { final JaxbEmbeddedIdImpl jaxbEmbeddedId = (JaxbEmbeddedIdImpl) jaxbPersistentAttribute; - // need target-class here... - throw new UnsupportedOperationException( "Not yet implemented" ); + final String target = jaxbEmbeddedId.getEmbeddable(); + if ( StringHelper.isEmpty( target ) ) { + return null; + } + final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); + return classDetailsRegistry.resolveClassDetails( + target, + () -> new DynamicClassDetails( target, sourceModelBuildingContext ) + ); } if ( jaxbPersistentAttribute instanceof JaxbBasicImpl ) { final JaxbBasicImpl jaxbBasic = (JaxbBasicImpl) jaxbPersistentAttribute; - if ( jaxbBasic.getJavaType() == null || jaxbBasic.getJavaType().getClazz() == null ) { - return null; - } - else { - return XmlAnnotationHelper.resolveJavaType( - jaxbBasic.getJavaType().getClazz(), - sourceModelBuildingContext - ); - } + return XmlAnnotationHelper.resolveJavaType( jaxbBasic.getTarget(), sourceModelBuildingContext ); } if ( jaxbPersistentAttribute instanceof JaxbEmbeddedImpl ) { final JaxbEmbeddedImpl jaxbEmbedded = (JaxbEmbeddedImpl) jaxbPersistentAttribute; - if ( jaxbEmbedded.getEmbeddable() == null ) { + final String target = jaxbEmbedded.getTarget(); + if ( StringHelper.isEmpty( target ) ) { return null; } final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); return classDetailsRegistry.resolveClassDetails( - jaxbEmbedded.getEmbeddable(), + target, + () -> new DynamicClassDetails( target, sourceModelBuildingContext ) + ); + } + + if ( jaxbPersistentAttribute instanceof JaxbOneToOneImpl ) { + final JaxbOneToOneImpl jaxbOneToOne = (JaxbOneToOneImpl) jaxbPersistentAttribute; + final String target = jaxbOneToOne.getTargetEntity(); + if ( StringHelper.isEmpty( target ) ) { + return null; + } + final ClassDetailsRegistry classDetailsRegistry = sourceModelBuildingContext.getClassDetailsRegistry(); + return classDetailsRegistry.resolveClassDetails( + target, () -> new DynamicClassDetails( - jaxbEmbedded.getEmbeddable(), + target, null, false, null, @@ -352,11 +357,6 @@ private static ClassDetails determineDynamicAttributeJavaType( ); } - if ( jaxbPersistentAttribute instanceof JaxbOneToOneImpl ) { - final JaxbOneToOneImpl jaxbOneToOne = (JaxbOneToOneImpl) jaxbPersistentAttribute; - final String targetEntity = jaxbOneToOne.getTargetEntity(); - } - if ( jaxbPersistentAttribute instanceof JaxbAnyMappingImpl ) { return sourceModelBuildingContext.getClassDetailsRegistry().getClassDetails( Object.class.getName() ); } diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java index db4618c..79f6820 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java @@ -7,6 +7,7 @@ package org.hibernate.models.orm.xml.internal; import java.lang.annotation.Annotation; +import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -15,6 +16,7 @@ import org.hibernate.annotations.AttributeAccessor; import org.hibernate.annotations.Formula; +import org.hibernate.annotations.JavaType; import org.hibernate.annotations.JdbcType; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.Nationalized; @@ -28,6 +30,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbAssociationOverrideImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbAttributeOverrideImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicMapping; import org.hibernate.boot.jaxb.mapping.spi.JaxbCachingImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbConfigurationParameterImpl; @@ -36,17 +39,15 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity; import org.hibernate.boot.jaxb.mapping.spi.JaxbGeneratedValueImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbIdImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbJavaTypeImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbJdbcTypeImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbLobImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbNationalizedImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbNaturalId; -import org.hibernate.boot.jaxb.mapping.spi.JaxbNaturalIdImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbSequenceGeneratorImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbTableGeneratorImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbTableImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbUuidGeneratorImpl; +import org.hibernate.models.ModelsException; import org.hibernate.models.internal.CollectionHelper; import org.hibernate.models.internal.StringHelper; import org.hibernate.models.orm.xml.spi.PersistenceUnitMetadata; @@ -60,6 +61,7 @@ import org.hibernate.models.source.spi.ClassDetails; import org.hibernate.models.source.spi.ClassDetailsRegistry; import org.hibernate.models.source.spi.SourceModelBuildingContext; +import org.hibernate.type.SqlTypes; import jakarta.persistence.Access; import jakarta.persistence.AccessType; @@ -287,47 +289,6 @@ public static void applyTargetClass( targetAnn.setAttributeValue( "value", classDetails ); } - public static void applyJdbcType( - JaxbJdbcTypeImpl jaxbJdbcType, - MutableMemberDetails memberDetails, - SourceModelBuildingContext sourceModelBuildingContext) { - if ( jaxbJdbcType == null ) { - return; - } - - if ( jaxbJdbcType.getCode() != null ) { - applyJdbcTypeCode( jaxbJdbcType.getCode(), memberDetails, sourceModelBuildingContext ); - } - else if ( jaxbJdbcType.getDescriptor() != null ) { - applyJdbcTypeDescriptor( jaxbJdbcType.getDescriptor(), memberDetails, sourceModelBuildingContext ); - } - } - - private static void applyJdbcTypeDescriptor( - String descriptorName, - MutableMemberDetails memberDetails, - SourceModelBuildingContext sourceModelBuildingContext) { - final ClassDetails descriptorClassDetails = sourceModelBuildingContext - .getClassDetailsRegistry() - .resolveClassDetails( descriptorName ); - final DynamicAnnotationUsage jdbcTypeAnn = makeAnnotation( JdbcType.class, memberDetails ); - jdbcTypeAnn.setAttributeValue( "value", descriptorClassDetails ); - - } - - public static void applyJdbcTypeCode( - Integer jdbcTypeCode, - MutableMemberDetails memberDetails, - SourceModelBuildingContext sourceModelBuildingContext) { - if ( jdbcTypeCode == null ) { - return; - } - - final DynamicAnnotationUsage typeCodeAnn = new DynamicAnnotationUsage<>( JdbcTypeCode.class, memberDetails ); - memberDetails.addAnnotationUsage( typeCodeAnn ); - typeCodeAnn.setAttributeValue( "value", jdbcTypeCode ); - } - public static void applyTemporal( TemporalType temporalType, MutableMemberDetails memberDetails, @@ -717,4 +678,82 @@ else if ( UUID.class.getSimpleName().equals( value ) ) { return sourceModelBuildingContext.getClassDetailsRegistry().resolveClassDetails( value ); } + + public static void applyBasicTypeComposition( + JaxbBasicMapping jaxbBasicMapping, + MutableMemberDetails memberDetails, + SourceModelBuildingContext sourceModelBuildingContext) { + if ( jaxbBasicMapping.getType() != null ) { + applyUserType( jaxbBasicMapping.getType(), memberDetails, sourceModelBuildingContext ); + } + else if ( jaxbBasicMapping.getJavaType() != null ) { + applyJavaTypeDescriptor( jaxbBasicMapping.getJavaType(), memberDetails, sourceModelBuildingContext ); + } + else if ( StringHelper.isNotEmpty( jaxbBasicMapping.getTarget() ) ) { + applyTargetClass( jaxbBasicMapping.getTarget(), memberDetails, sourceModelBuildingContext ); + } + + if ( StringHelper.isNotEmpty( jaxbBasicMapping.getJdbcType() ) ) { + applyJdbcTypeDescriptor( jaxbBasicMapping.getJdbcType(), memberDetails, sourceModelBuildingContext ); + } + else if ( jaxbBasicMapping.getJdbcTypeCode() != null ) { + applyJdbcTypeCode( jaxbBasicMapping.getJdbcTypeCode(), memberDetails, sourceModelBuildingContext ); + } + else if ( StringHelper.isNotEmpty( jaxbBasicMapping.getJdbcTypeName() ) ) { + applyJdbcTypeCode( + resolveJdbcTypeName( jaxbBasicMapping.getJdbcTypeName() ), + memberDetails, + sourceModelBuildingContext + ); + } + } + + private static int resolveJdbcTypeName(String name) { + try { + final Field matchingField = SqlTypes.class.getDeclaredField( name ); + return matchingField.getInt( null ); + } + catch (NoSuchFieldException | IllegalAccessException e) { + throw new ModelsException( "Could not resolve " + name + "", e ); + } + } + + public static void applyJavaTypeDescriptor( + String descriptorClassName, + MutableMemberDetails memberDetails, + SourceModelBuildingContext sourceModelBuildingContext) { + final DynamicAnnotationUsage typeAnn = new DynamicAnnotationUsage<>( JavaType.class, memberDetails ); + memberDetails.addAnnotationUsage( typeAnn ); + + final ClassDetails descriptorClass = sourceModelBuildingContext + .getClassDetailsRegistry() + .resolveClassDetails( descriptorClassName ); + typeAnn.setAttributeValue( "value", descriptorClass ); + } + + + private static void applyJdbcTypeDescriptor( + String descriptorClassName, + MutableMemberDetails memberDetails, + SourceModelBuildingContext sourceModelBuildingContext) { + final ClassDetails descriptorClassDetails = sourceModelBuildingContext + .getClassDetailsRegistry() + .resolveClassDetails( descriptorClassName ); + final DynamicAnnotationUsage jdbcTypeAnn = makeAnnotation( JdbcType.class, memberDetails ); + jdbcTypeAnn.setAttributeValue( "value", descriptorClassDetails ); + + } + + public static void applyJdbcTypeCode( + Integer jdbcTypeCode, + MutableMemberDetails memberDetails, + SourceModelBuildingContext sourceModelBuildingContext) { + if ( jdbcTypeCode == null ) { + return; + } + + final DynamicAnnotationUsage typeCodeAnn = new DynamicAnnotationUsage<>( JdbcTypeCode.class, memberDetails ); + memberDetails.addAnnotationUsage( typeCodeAnn ); + typeCodeAnn.setAttributeValue( "value", jdbcTypeCode ); + } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java index 15b07bf..59657e5 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java @@ -6,6 +6,7 @@ */ package org.hibernate.models.orm.xml.dynamic; +import org.hibernate.annotations.JavaType; import org.hibernate.models.orm.internal.ManagedResourcesImpl; import org.hibernate.models.orm.spi.EntityHierarchy; import org.hibernate.models.orm.spi.EntityTypeMetadata; @@ -66,7 +67,8 @@ public boolean shouldIgnoreUnlistedClasses() { assertThat( idField.getType().getClassName() ).isEqualTo( Integer.class.getName() ); final FieldDetails nameField = rootEntity.getClassDetails().findFieldByName( "name" ); - assertThat( nameField.getType().getClassName() ).isEqualTo( String.class.getName() ); + assertThat( nameField.getType().getClassName() ).isEqualTo( Object.class.getName() ); + assertThat( nameField.getAnnotationUsage( JavaType.class ) ).isNotNull(); final FieldDetails qtyField = rootEntity.getClassDetails().findFieldByName( "quantity" ); assertThat( qtyField.getType().getClassName() ).isEqualTo( int.class.getName() ); diff --git a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/dynamic/DynamicClassDetails.java b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/dynamic/DynamicClassDetails.java index 791d673..aad2996 100644 --- a/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/dynamic/DynamicClassDetails.java +++ b/hibernate-models-source/src/main/java/org/hibernate/models/source/internal/dynamic/DynamicClassDetails.java @@ -30,6 +30,14 @@ public class DynamicClassDetails extends AbstractAnnotationTarget implements Cla private Class javaType; + public DynamicClassDetails(String name, SourceModelBuildingContext buildingContext) { + this( name, null, buildingContext ); + } + + public DynamicClassDetails(String name, ClassDetails superType, SourceModelBuildingContext buildingContext) { + this( name, null, false, superType, buildingContext ); + } + public DynamicClassDetails( String name, String className,