diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java index 2e585ddcca..b37500b6fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java @@ -2586,8 +2586,10 @@ public abstract class CollectionBinder { } ); property.forEachAnnotationUsage( jakarta.persistence.JoinTable.class, - (usage) -> - TableBinder.addTableCheck( collectionTable, usage.findAttributeValue( "check" ) ) + (usage) -> { + TableBinder.addTableCheck( collectionTable, usage.findAttributeValue( "check" ) ); + TableBinder.addTableComment( collectionTable, usage.getString( "comment" ) ); + } ); } 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 a29c3c90a4..cf394a7f96 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 @@ -449,7 +449,8 @@ public class EntityBinder { if ( jpaTableUsage != null ) { final Table table = persistentClass.getTable(); TableBinder.addJpaIndexes( table, jpaTableUsage.getList( "indexes" ), context ); - TableBinder.addTableCheck( table, jpaTableUsage.findAttributeValue( "check" ) ); + TableBinder.addTableCheck( table, jpaTableUsage.findAttributeValue( "check" ) ); + TableBinder.addTableComment( table, jpaTableUsage.getString( "comment" ) ); } final InFlightMetadataCollector.EntityTableXref entityTableXref = context @@ -2179,7 +2180,9 @@ public class EntityBinder { joinTable.getList( "joinColumns" ), joinTable.getList( "uniqueConstraints" ) ); - TableBinder.addTableCheck( join.getTable(), joinTable.findAttributeValue( "check" )); + final Table table = join.getTable(); + TableBinder.addTableCheck( table, joinTable.findAttributeValue( "check" ) ); + TableBinder.addTableComment( table, joinTable.getString( "comment" ) ); return join; } @@ -2196,7 +2199,8 @@ public class EntityBinder { ); final Table table = join.getTable(); new IndexBinder( context ).bindIndexes( table, secondaryTable.getList( "indexes" ) ); - TableBinder.addTableCheck( table, secondaryTable.findAttributeValue( "check" )); + TableBinder.addTableCheck( table, secondaryTable.findAttributeValue( "check" ) ); + TableBinder.addTableComment( table, secondaryTable.getString( "comment" ) ); return join; } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java index 2de2908b1e..97bf75533d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java @@ -23,6 +23,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.dialect.Dialect; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.mapping.Any; +import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.mapping.CheckConstraint; import org.hibernate.mapping.Collection; @@ -888,6 +889,12 @@ public class TableBinder { } } + static void addTableComment(Table table, String comment) { + if ( StringHelper.isNotEmpty( comment ) ) { + table.setComment( comment ); + } + } + public void setDefaultName( String ownerClassName, String ownerEntity, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/JpaTableCommentTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/JpaTableCommentTest.java new file mode 100644 index 0000000000..a1cb7909c9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/JpaTableCommentTest.java @@ -0,0 +1,153 @@ +package org.hibernate.orm.test.schemaupdate.tablecomment; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.EnumSet; +import java.util.Locale; + +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.schema.TargetType; + +import org.hibernate.testing.orm.junit.BaseUnitTest; +import org.hibernate.testing.orm.junit.DialectFeatureChecks; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.RequiresDialectFeature; +import org.hibernate.testing.util.ServiceRegistryUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@JiraKey("HHH-18055") +@BaseUnitTest +@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsCommentOn.class) +public class JpaTableCommentTest { + static final String TABLE_NAME = "PRIMARY_TABLE"; + static final String TABLE_COMMENT = "This is the primary table"; + + static final String SECONDARY_TABLE_NAME = "SECOND_TABLE"; + static final String SECONDARY_TABLE_COMMENT = "This is the secondary table"; + + static final String JOIN_TABLE_NAME = "JOIN_TABLE"; + static final String JOIN_TABLE_COMMENT = "This is the join table"; + + private File output; + private StandardServiceRegistry ssr; + private MetadataImplementor metadata; + + @BeforeEach + public void setUp() throws IOException { + output = File.createTempFile( "update_script", ".sql" ); + output.deleteOnExit(); + ssr = ServiceRegistryUtil.serviceRegistry(); + } + + @AfterEach + public void tearsDown() { + output.delete(); + StandardServiceRegistryBuilder.destroy( ssr ); + } + + @Test + public void testTableCommentAreCreated() throws Exception { + createSchema( TestEntity.class ); + assertTrue( + tableCreationStatementContainsComment( output, TABLE_NAME, TABLE_COMMENT ), + "Table " + TABLE_NAME + " comment has not been created " + ); + + assertTrue( + tableCreationStatementContainsComment( output, SECONDARY_TABLE_NAME, SECONDARY_TABLE_COMMENT ), + "SecondaryTable " + SECONDARY_TABLE_NAME + " comment has not been created " + ); + + assertTrue( + tableCreationStatementContainsComment( output, JOIN_TABLE_NAME, JOIN_TABLE_COMMENT ), + "Join Table " + JOIN_TABLE_NAME + " comment has not been created " + ); + } + + @Test + public void testXmlMAppingTableCommentAreCreated() throws Exception { + createSchema( "org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.xml" ); + assertTrue( + tableCreationStatementContainsComment( output, TABLE_NAME, TABLE_COMMENT ), + "Table " + TABLE_NAME + " comment has not been created " + ); + + assertTrue( + tableCreationStatementContainsComment( output, JOIN_TABLE_NAME, JOIN_TABLE_COMMENT ), + "Join Table " + JOIN_TABLE_NAME + " comment has not been created " + ); + + assertTrue( + tableCreationStatementContainsComment( output, SECONDARY_TABLE_NAME, SECONDARY_TABLE_COMMENT ), + "SecondaryTable " + SECONDARY_TABLE_NAME + " comment has not been created " + ); + } + + private boolean tableCreationStatementContainsComment( + File output, + String tableName, + String comment) throws Exception { + String[] fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase() + .split( System.lineSeparator() ); + for ( int i = 0; i < fileContent.length; i++ ) { + String statement = fileContent[i].toUpperCase( Locale.ROOT ); + if ( !metadata.getDatabase().getDialect().getTableComment( "" ).isEmpty() ) { + if ( statement.contains( "CREATE TABLE " + tableName.toUpperCase( Locale.ROOT ) ) ) { + if ( statement.contains( comment.toUpperCase( Locale.ROOT ) ) ) { + return true; + } + } + } + else if ( statement.contains( "COMMENT ON TABLE " + tableName.toUpperCase( Locale.ROOT ) ) ) { + if ( statement.contains( comment.toUpperCase( Locale.ROOT ) ) ) { + return true; + } + } + } + return false; + } + + private void createSchema(String... xmlMapping) { + final MetadataSources metadataSources = new MetadataSources( ssr ); + + for ( String xml : xmlMapping ) { + metadataSources.addResource( xml ); + } + metadata = (MetadataImplementor) metadataSources.buildMetadata(); + metadata.orderColumns( false ); + metadata.validate(); + new SchemaExport() + .setHaltOnError( true ) + .setOutputFile( output.getAbsolutePath() ) + .setFormat( false ) + .create( EnumSet.of( TargetType.SCRIPT ), metadata ); + } + + private void createSchema(Class... annotatedClasses) { + final MetadataSources metadataSources = new MetadataSources( ssr ); + + for ( Class c : annotatedClasses ) { + metadataSources.addAnnotatedClass( c ); + } + metadata = (MetadataImplementor) metadataSources.buildMetadata(); + metadata.orderColumns( false ); + metadata.validate(); + new SchemaExport() + .setHaltOnError( true ) + .setOutputFile( output.getAbsolutePath() ) + .setFormat( false ) + .create( EnumSet.of( TargetType.SCRIPT ), metadata ); + } + + + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.java new file mode 100644 index 0000000000..f8e419071d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.java @@ -0,0 +1,69 @@ +package org.hibernate.orm.test.schemaupdate.tablecomment; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SecondaryTable; +import jakarta.persistence.Table; + +@Entity +@Table( + name = JpaTableCommentTest.TABLE_NAME, + comment = JpaTableCommentTest.TABLE_COMMENT +) +@SecondaryTable( + name = JpaTableCommentTest.SECONDARY_TABLE_NAME, + comment = JpaTableCommentTest.SECONDARY_TABLE_COMMENT +) +public class TestEntity { + @Id + private Long id; + + @Column(name = "NAME_COLUMN") + private String name; + + @Column(name = "SECOND_NAME", table = JpaTableCommentTest.SECONDARY_TABLE_NAME) + private String secondName; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinTable( + name = JpaTableCommentTest.JOIN_TABLE_NAME, + comment = JpaTableCommentTest.JOIN_TABLE_COMMENT + ) + private TestEntity testEntity; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSecondName() { + return secondName; + } + + public void setSecondName(String secondName) { + this.secondName = secondName; + } + + public TestEntity getTestEntity() { + return testEntity; + } + + public void setTestEntity(TestEntity testEntity) { + this.testEntity = testEntity; + } +} diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.xml b/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.xml new file mode 100644 index 0000000000..9882907a6b --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/schemaupdate/tablecomment/TestEntity.xml @@ -0,0 +1,27 @@ + + + + org.hibernate.orm.test.schemaupdate.tablecomment + + + + + + + + + + + + + + + + + \ No newline at end of file