diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java index c6da710287..576179b27a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/GenerationStrategyInterpreter.java @@ -131,6 +131,14 @@ public void interpretTableGenerator( ); } + final String options = tableGeneratorAnnotation.getString( "options" ); + if ( StringHelper.isNotEmpty( options ) ) { + definitionBuilder.addParam( + org.hibernate.id.enhanced.TableGenerator.TABLE_OPTIONS, + options + ); + } + definitionBuilder.addParam( org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM, String.valueOf( tableGeneratorAnnotation.getInteger( "allocationSize" ) ) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java index c9b77a71a4..20aaef95b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/ManagedTypeProcessor.java @@ -596,6 +596,8 @@ private static void processEntityMetadata( jaxbEntity, classDetails, xmlDocumentContext ); + XmlAnnotationHelper.applyTableGenerators( jaxbEntity.getTableGenerators(), classDetails, xmlDocumentContext ); + renderClass( classDetails, xmlDocumentContext ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java index d78b2ecdb8..22cb1a3acf 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java @@ -131,6 +131,7 @@ import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.persistence.TableGenerator; +import jakarta.persistence.TableGenerators; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; import jakarta.persistence.UniqueConstraint; @@ -389,6 +390,27 @@ public static void applyUniqueConstraints( } ); } + public static void applyUniqueConstraints( + List jaxbUniqueConstraints, + MutableAnnotationUsage annotationUsage, + XmlDocumentContext xmlDocumentContext) { + if ( CollectionHelper.isEmpty( jaxbUniqueConstraints ) ) { + return; + } + + final List> uniqueConstraintUsages = new ArrayList<>( jaxbUniqueConstraints.size() ); + annotationUsage.setAttributeValue( "uniqueConstraints", uniqueConstraintUsages ); + + jaxbUniqueConstraints.forEach( (jaxbUniqueConstraint) -> { + final MutableAnnotationUsage ucUsage = + JpaAnnotations.UNIQUE_CONSTRAINT.createUsage( xmlDocumentContext.getModelBuildingContext() ); + XmlAnnotationHelper.applyOptionalAttribute( ucUsage, "name", jaxbUniqueConstraint.getName() ); + XmlAnnotationHelper.applyOptionalAttribute( ucUsage, "options", jaxbUniqueConstraint.getOptions() ); + ucUsage.setAttributeValue( "columnNames", jaxbUniqueConstraint.getColumnName() ); + uniqueConstraintUsages.add( ucUsage ); + } ); + } + public static void applyIndexes( List jaxbIndexes, AnnotationTarget target, @@ -405,6 +427,29 @@ public static void applyIndexes( applyOr( jaxbIndex, JaxbIndexImpl::getName, "name", indexAnn, JpaAnnotations.INDEX ); applyOr( jaxbIndex, JaxbIndexImpl::getColumnList, "columnList", indexAnn, JpaAnnotations.INDEX ); applyOr( jaxbIndex, JaxbIndexImpl::isUnique, "unique", indexAnn, JpaAnnotations.INDEX ); + applyOr( jaxbIndex, JaxbIndexImpl::getOptions, "options", indexAnn, JpaAnnotations.INDEX ); + indexes.add( indexAnn ); + } ); + + annotationUsage.setAttributeValue( "indexes", indexes ); + } + + public static void applyIndexes( + List jaxbIndexes, + MutableAnnotationUsage annotationUsage, + XmlDocumentContext xmlDocumentContext) { + if ( CollectionHelper.isEmpty( jaxbIndexes ) ) { + return; + } + + final List> indexes = new ArrayList<>( jaxbIndexes.size() ); + jaxbIndexes.forEach( jaxbIndex -> { + final MutableAnnotationUsage indexAnn = + JpaAnnotations.INDEX.createUsage( xmlDocumentContext.getModelBuildingContext() ); + applyOr( jaxbIndex, JaxbIndexImpl::getName, "name", indexAnn, JpaAnnotations.INDEX ); + applyOr( jaxbIndex, JaxbIndexImpl::getColumnList, "columnList", indexAnn, JpaAnnotations.INDEX ); + applyOr( jaxbIndex, JaxbIndexImpl::isUnique, "unique", indexAnn, JpaAnnotations.INDEX ); + applyOr( jaxbIndex, JaxbIndexImpl::getOptions, "options", indexAnn, JpaAnnotations.INDEX ); indexes.add( indexAnn ); } ); @@ -528,6 +573,24 @@ public static void applySequenceGenerator( XmlProcessingHelper.applyAttributeIfSpecified( "options", jaxbGenerator.getOptions(), sequenceAnn ); } + public static void applyTableGenerators( + JaxbTableGeneratorImpl jaxbGenerator, + MutableClassDetails classDetails, + XmlDocumentContext xmlDocumentContext) { + if ( jaxbGenerator == null ) { + return; + } + + final MutableAnnotationUsage tableAnn = classDetails.replaceAnnotationUsage( + JpaAnnotations.TABLE_GENERATOR, + xmlDocumentContext.getModelBuildingContext() + ); + + applyTableGeneratorAttributes( jaxbGenerator, tableAnn ); + applyUniqueConstraints( jaxbGenerator.getUniqueConstraints(), tableAnn, xmlDocumentContext ); + applyIndexes( jaxbGenerator.getIndexes(), tableAnn, xmlDocumentContext ); + } + public static void applyTableGenerator( JaxbTableGeneratorImpl jaxbGenerator, MutableMemberDetails memberDetails, @@ -537,6 +600,14 @@ public static void applyTableGenerator( } final MutableAnnotationUsage tableAnn = memberDetails.applyAnnotationUsage( JpaAnnotations.TABLE_GENERATOR, xmlDocumentContext.getModelBuildingContext() ); + applyTableGeneratorAttributes( jaxbGenerator, tableAnn ); + applyUniqueConstraints( jaxbGenerator.getUniqueConstraints(), memberDetails, tableAnn, xmlDocumentContext ); + applyIndexes( jaxbGenerator.getIndexes(), memberDetails, tableAnn, xmlDocumentContext ); + } + + private static void applyTableGeneratorAttributes( + JaxbTableGeneratorImpl jaxbGenerator, + MutableAnnotationUsage tableAnn) { XmlProcessingHelper.applyAttributeIfSpecified( "name", jaxbGenerator.getName(), tableAnn ); XmlProcessingHelper.applyAttributeIfSpecified( "table", jaxbGenerator.getTable(), tableAnn ); XmlProcessingHelper.applyAttributeIfSpecified( "catalog", jaxbGenerator.getCatalog(), tableAnn ); @@ -546,8 +617,7 @@ public static void applyTableGenerator( XmlProcessingHelper.applyAttributeIfSpecified( "pkColumnValue", jaxbGenerator.getPkColumnValue(), tableAnn ); XmlProcessingHelper.applyAttributeIfSpecified( "initialValue", jaxbGenerator.getInitialValue(), tableAnn ); XmlProcessingHelper.applyAttributeIfSpecified( "allocationSize", jaxbGenerator.getInitialValue(), tableAnn ); - applyUniqueConstraints( jaxbGenerator.getUniqueConstraints(), memberDetails, tableAnn, xmlDocumentContext ); - applyIndexes( jaxbGenerator.getIndexes(), memberDetails, tableAnn, xmlDocumentContext ); + XmlProcessingHelper.applyAttributeIfSpecified( "options", jaxbGenerator.getOptions(), tableAnn ); } public static void applyUuidGenerator( diff --git a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java index c0935977a0..df2846c9d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java @@ -196,6 +196,11 @@ public class TableGenerator implements PersistentIdentifierGenerator { */ public static final int DEF_SEGMENT_LENGTH = 255; + /** + * Configures the options of the table to use. + */ + public static final String TABLE_OPTIONS = "options"; + private boolean storeLastUsedValue; @@ -221,6 +226,7 @@ public class TableGenerator implements PersistentIdentifierGenerator { private String contributor; + private String options; /** * Type mapping for the identifier. * @@ -359,6 +365,7 @@ public void configure(Type type, Properties parameters, ServiceRegistry serviceR if ( contributor == null ) { contributor = "orm"; } + options = parameters.getProperty( TABLE_OPTIONS ); } private static OptimizerDescriptor determineOptimizationStrategy(Properties parameters, int incrementSize) { @@ -727,6 +734,9 @@ public void registerExportables(Database database) { qualifiedTableName.getObjectName(), (identifier) -> new Table( contributor, namespace, identifier, false ) ); + if ( StringHelper.isNotEmpty( options ) ) { + table.setOptions( options ); + } final BasicTypeRegistry basicTypeRegistry = database.getTypeConfiguration().getBasicTypeRegistry(); // todo : not sure the best solution here. do we add the columns if missing? other? diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TableOptionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TableOptionsTest.java index 9b9549a165..e50cabed7a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TableOptionsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TableOptionsTest.java @@ -23,6 +23,10 @@ @BaseUnitTest public class TableOptionsTest { + + static final String TABLE_GENERATOR_NAME = "TEST_TABLE_GENERATOR"; + static final String TABLE_GENERATOR_OPTIONS = "option_0"; + static final String TABLE_NAME = "PRIMARY_TABLE"; static final String TABLE_OPTIONS = "option_1"; @@ -53,7 +57,7 @@ public void tearsDown() { } @Test - public void testTableCommentAreCreated() throws Exception { + public void testTableOptionsAreCreated() throws Exception { createSchema( TestEntity.class ); assertTrue( tableCreationStatementContainsOptions( output, TABLE_NAME, TABLE_OPTIONS ), @@ -67,12 +71,17 @@ public void testTableCommentAreCreated() throws Exception { assertTrue( tableCreationStatementContainsOptions( output, JOIN_TABLE_NAME, JOIN_TABLE_OPTIONS ), - "Join Table " + JOIN_TABLE_NAME + " options has not been created " + "JoinTable " + JOIN_TABLE_NAME + " options has not been created " ); assertTrue( tableCreationStatementContainsOptions( output, COLLECTION_TABLE_NAME, COLLECTION_TABLE_OPTIONS ), - "Join Table " + COLLECTION_TABLE_NAME + " options has not been created " + "JoinTable " + COLLECTION_TABLE_NAME + " options has not been created " + ); + + assertTrue( + tableCreationStatementContainsOptions( output, TABLE_GENERATOR_NAME, TABLE_GENERATOR_OPTIONS ), + "TableGenerator " + COLLECTION_TABLE_NAME + " options has not been created " ); } @@ -98,6 +107,11 @@ public void testXmlMappingTableCommentAreCreated() throws Exception { tableCreationStatementContainsOptions( output, COLLECTION_TABLE_NAME, COLLECTION_TABLE_OPTIONS ), "Join Table " + COLLECTION_TABLE_NAME + " options has not been created " ); + + assertTrue( + tableCreationStatementContainsOptions( output, TABLE_GENERATOR_NAME, TABLE_GENERATOR_OPTIONS ), + "TableGenerator " + TABLE_GENERATOR_NAME + " options has not been created " + ); } private static boolean tableCreationStatementContainsOptions( @@ -130,7 +144,7 @@ private void createSchema(String... xmlMapping) { .setHaltOnError( true ) .setOutputFile( output.getAbsolutePath() ) .setFormat( false ) - .create( EnumSet.of( TargetType.SCRIPT ), metadata ); + .createOnly( EnumSet.of( TargetType.SCRIPT ), metadata ); } private void createSchema(Class... annotatedClasses) { @@ -146,7 +160,7 @@ private void createSchema(Class... annotatedClasses) { .setHaltOnError( true ) .setOutputFile( output.getAbsolutePath() ) .setFormat( false ) - .create( EnumSet.of( TargetType.SCRIPT ), metadata ); + .createOnly( EnumSet.of( TargetType.SCRIPT ), metadata ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.java index 2c0d933d93..d8b8ca333a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.java @@ -7,12 +7,15 @@ import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Index; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToOne; import jakarta.persistence.SecondaryTable; import jakarta.persistence.Table; +import jakarta.persistence.TableGenerator; @Entity @Table( @@ -25,6 +28,12 @@ ) public class TestEntity { @Id + @TableGenerator( + name = "id-table-generator", + table = TableOptionsTest.TABLE_GENERATOR_NAME, + options = TableOptionsTest.TABLE_GENERATOR_OPTIONS + ) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "id-table-generator") private Long id; @Column(name = "NAME_COLUMN") diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.xml b/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.xml index 40b4078472..aa495b0b9e 100644 --- a/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.xml +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tableoptions/TestEntity.xml @@ -10,8 +10,11 @@ + - + + +