diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java index 813b6282c2c7..a044b11d5173 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java @@ -91,14 +91,12 @@ public class AnnotatedColumn { private String defaultValue; private String generatedAs; -// private String comment; private final List checkConstraints = new ArrayList<>(); private AnnotatedColumns parent; - private String options; - - private String comment; + String options; + String comment; public AnnotatedColumns getParent() { return parent; @@ -1050,4 +1048,7 @@ void setOptions(String options){ this.options = options; } + void setComment(String comment){ + this.comment = comment; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java index 887812a1a145..401ac23053d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java @@ -191,7 +191,8 @@ public void applyJoinAnnotation(JoinColumn joinColumn, String defaultName) { setUpdatable( joinColumn.updatable() ); setReferencedColumn( joinColumn.referencedColumnName() ); applyColumnCheckConstraint( joinColumn ); - setOptions( joinColumn.options() ); + applyColumnComment( joinColumn ); + applyColumnOptions( joinColumn ); final String table = joinColumn.table(); if ( table.isBlank() ) { @@ -234,17 +235,20 @@ private static AnnotatedJoinColumn buildExplicitInheritanceJoinColumn( final String columnDefinition; final String referencedColumnName; final String options; + final String comment; if ( primaryKeyJoinColumn != null ) { columnName = primaryKeyJoinColumn.name(); columnDefinition = primaryKeyJoinColumn.columnDefinition(); referencedColumnName = primaryKeyJoinColumn.referencedColumnName(); options = primaryKeyJoinColumn.options(); + comment = null; } else { columnName = joinColumn.name(); columnDefinition = joinColumn.columnDefinition(); referencedColumnName = joinColumn.referencedColumnName(); options = joinColumn.options(); + comment = joinColumn.comment(); } final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer(); @@ -259,6 +263,7 @@ private static AnnotatedJoinColumn buildExplicitInheritanceJoinColumn( // column.setPropertyHolder(propertyHolder); // column.setJoins(joins); // column.setContext( context ); + column.setComment( comment ); column.setOptions( options ); column.setImplicit( false ); column.setNullable( false ); @@ -508,7 +513,7 @@ public AnnotatedJoinColumns getParent() { @Override public void setParent(AnnotatedColumns parent) { - if ( !(parent instanceof AnnotatedJoinColumns) ) { + if ( !(parent instanceof AnnotatedJoinColumns) ) { throw new UnsupportedOperationException("wrong kind of parent"); } super.setParent( parent ); @@ -521,4 +526,14 @@ public void setParent(AnnotatedJoinColumns parent) { private void applyColumnCheckConstraint(jakarta.persistence.JoinColumn column) { applyCheckConstraints( column.check() ); } + + private void applyColumnOptions(jakarta.persistence.JoinColumn column) { + options = column.options(); + } + + private void applyColumnComment(jakarta.persistence.JoinColumn column) { + if ( !column.comment().isBlank() ) { + comment = column.comment(); + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentTest.java new file mode 100644 index 000000000000..d47f529deef0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentTest.java @@ -0,0 +1,67 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.annotations.comment.jpa; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Table; +import org.hibernate.testing.orm.junit.BaseUnitTest; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.util.ServiceRegistryUtil; +import org.junit.jupiter.api.Test; + +import java.util.stream.StreamSupport; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +/** + * @author Yanming Zhou + */ +@BaseUnitTest +public class CommentTest { + + private static final String TABLE_NAME = "TestEntity"; + private static final String TABLE_COMMENT = "I am table"; + + @Test + @JiraKey(value = "HHH-4369") + public void testComments() { + StandardServiceRegistry ssr = ServiceRegistryUtil.serviceRegistry(); + Metadata metadata = new MetadataSources(ssr).addAnnotatedClass(TestEntity.class).buildMetadata(); + Table table = StreamSupport.stream(metadata.getDatabase().getNamespaces().spliterator(), false) + .flatMap(namespace -> namespace.getTables().stream()).filter(t -> t.getName().equals(TABLE_NAME)) + .findFirst().orElse(null); + assertThat(table.getComment(), is(TABLE_COMMENT)); + for (Column col : table.getColumns()) { + assertThat(col.getComment(), is("I am " + col.getName())); + } + } + + @Entity(name = "Person") + @jakarta.persistence.Table(name = TABLE_NAME, comment = TABLE_COMMENT) + public static class TestEntity { + + @Id + @GeneratedValue + @jakarta.persistence.Column(comment = "I am id") + private Long id; + + @jakarta.persistence.Column(length = 50, comment = "I am name") + private String name; + + @ManyToOne + @JoinColumn(name = "other", comment = "I am other") + private TestEntity other; + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentsTest.java new file mode 100644 index 000000000000..9034e203d2f8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/comment/jpa/CommentsTest.java @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.annotations.comment.jpa; + +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SecondaryTable; +import jakarta.persistence.Table; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.testing.orm.junit.BaseUnitTest; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.util.ServiceRegistryUtil; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Currency; +import java.util.stream.StreamSupport; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +/** + * @author Yanming Zhou + */ +@BaseUnitTest +public class CommentsTest { + + private static final String TABLE_NAME = "TestEntity"; + private static final String SEC_TABLE_NAME = "TestEntity2"; + private static final String TABLE_COMMENT = "I am a table"; + private static final String SEC_TABLE_COMMENT = "I am a table too"; + + @Test + @JiraKey(value = "HHH-4369") + public void testComments() { + StandardServiceRegistry ssr = ServiceRegistryUtil.serviceRegistry(); + Metadata metadata = new MetadataSources(ssr).addAnnotatedClass(TestEntity.class).buildMetadata(); + org.hibernate.mapping.Table table = StreamSupport.stream(metadata.getDatabase().getNamespaces().spliterator(), false) + .flatMap(namespace -> namespace.getTables().stream()).filter(t -> t.getName().equals(TABLE_NAME)) + .findFirst().orElse(null); + assertThat(table.getComment(), is(TABLE_COMMENT)); + assertThat(table.getColumns().size(), is(6)); + for (org.hibernate.mapping.Column col : table.getColumns()) { + assertThat(col.getComment(), is("I am " + col.getName())); + } + table = StreamSupport.stream(metadata.getDatabase().getNamespaces().spliterator(), false) + .flatMap(namespace -> namespace.getTables().stream()).filter(t -> t.getName().equals(SEC_TABLE_NAME)) + .findFirst().orElse(null); + assertThat(table.getComment(), is(SEC_TABLE_COMMENT)); + assertThat(table.getColumns().size(), is(2)); + long count = table.getColumns().stream().filter(col -> "This is a date".equalsIgnoreCase(col.getComment())).count(); + assertThat(count, is(1L)); + } + + @Entity(name = "Person") + @Table(name = TABLE_NAME, comment = TABLE_COMMENT) + @SecondaryTable(name = SEC_TABLE_NAME, comment = SEC_TABLE_COMMENT) + public static class TestEntity { + + @Id + @GeneratedValue + @Column(comment = "I am id") + private Long id; + + @AttributeOverride(name = "firstName", column = @Column(comment = "I am firstName")) + @AttributeOverride(name = "lastName", column = @Column(comment = "I am lastName")) + private Name name; + + private Money money; + + @Column(table = SEC_TABLE_NAME, comment = "This is a date") + private LocalDate localDate; + + @ManyToOne + @JoinColumn(name = "other", comment = "I am other") + private TestEntity other; + + } + + @Embeddable + public static class Name { + private String firstName; + private String lastName; + } + + @Embeddable + public static class Money { + @Column(comment = "I am amount") + private BigDecimal amount; + @Column(comment = "I am currency") + private Currency currency; + } + +}