HHH-4369 Introduce @Comment for comment on column

This commit is contained in:
Yanming Zhou 2020-10-23 15:08:36 +08:00 committed by Sanne Grinovero
parent 5ffed50f1f
commit 99f027166d
8 changed files with 159 additions and 2 deletions

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* SQL column comment which can be defined at property level.
*
* @author Yanming Zhou
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Comment {
/**
* The comment string.
*/
String value();
}

View File

@ -83,6 +83,7 @@ import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.DiscriminatorFormula;
import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.annotations.Fetch;
@ -1998,6 +1999,7 @@ public final class AnnotationBinder {
elementColumns = Ejb3Column.buildColumnFromAnnotation(
new Column[] { ann },
formulaAnn,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
virtualProperty,
@ -2010,6 +2012,7 @@ public final class AnnotationBinder {
elementColumns = Ejb3Column.buildColumnFromAnnotation(
anns.columns(),
null,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
virtualProperty,
@ -2021,6 +2024,7 @@ public final class AnnotationBinder {
elementColumns = Ejb3Column.buildColumnFromAnnotation(
null,
null,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
virtualProperty,
@ -2050,6 +2054,7 @@ public final class AnnotationBinder {
Ejb3Column[] mapColumns = Ejb3Column.buildColumnFromAnnotation(
keyColumns,
null,
property.getAnnotation( Comment.class ),
Nullability.FORCED_NOT_NULL,
propertyHolder,
isJPA2 ? inferredData : mapKeyVirtualProperty,
@ -2098,6 +2103,7 @@ public final class AnnotationBinder {
PropertyData mapKeyVirtualProperty = new WrappedInferredData( inferredData, "mapkey" );
Ejb3JoinColumn[] mapJoinColumns = Ejb3JoinColumn.buildJoinColumnsWithDefaultColumnSuffix(
joinKeyColumns,
property.getAnnotation( Comment.class ),
null,
entityBinder.getSecondaryTables(),
propertyHolder,

View File

@ -998,6 +998,7 @@ public class BinderHelper {
Ejb3Column[] metaColumns = Ejb3Column.buildColumnFromAnnotation(
new javax.persistence.Column[] { metaColumn },
null,
null,
nullability,
propertyHolder,
inferredData,

View File

@ -17,6 +17,7 @@ import javax.persistence.OneToOne;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinColumnsOrFormulas;
@ -78,6 +79,7 @@ class ColumnsBuilder {
columns = Ejb3Column.buildColumnFromAnnotation(
new Column[] { ann },
formulaAnn,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
inferredData,
@ -90,6 +92,7 @@ class ColumnsBuilder {
columns = Ejb3Column.buildColumnFromAnnotation(
anns.columns(),
null,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
inferredData,
@ -115,6 +118,7 @@ class ColumnsBuilder {
"";
joinColumns = Ejb3JoinColumn.buildJoinColumns(
null,
property.getAnnotation( Comment.class ),
mappedBy,
entityBinder.getSecondaryTables(),
propertyHolder,
@ -131,6 +135,7 @@ class ColumnsBuilder {
columns = Ejb3Column.buildColumnFromAnnotation(
null,
null,
property.getAnnotation( Comment.class ),
nullability,
propertyHolder,
inferredData,
@ -154,6 +159,7 @@ class ColumnsBuilder {
if ( joinTableAnn != null ) {
joinColumns = Ejb3JoinColumn.buildJoinColumns(
joinTableAnn.inverseJoinColumns(),
property.getAnnotation( Comment.class ),
null,
entityBinder.getSecondaryTables(),
propertyHolder,
@ -174,6 +180,7 @@ class ColumnsBuilder {
: null;
joinColumns = Ejb3JoinColumn.buildJoinColumns(
null,
property.getAnnotation( Comment.class ),
mappedBy,
entityBinder.getSecondaryTables(),
propertyHolder,
@ -203,6 +210,7 @@ class ColumnsBuilder {
if ( joinColumnAnnotations != null ) {
return Ejb3JoinColumn.buildJoinColumns(
joinColumnAnnotations,
property.getAnnotation( Comment.class ),
null,
entityBinder.getSecondaryTables(),
propertyHolder,

View File

@ -13,6 +13,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.ColumnTransformer;
import org.hibernate.annotations.ColumnTransformers;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.model.naming.Identifier;
@ -70,6 +71,8 @@ public class Ejb3Column {
private String defaultValue;
private String comment;
public void setTable(Table table) {
this.table = table;
}
@ -193,6 +196,14 @@ public class Ejb3Column {
this.defaultValue = defaultValue;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Ejb3Column() {
}
@ -209,6 +220,9 @@ public class Ejb3Column {
if ( defaultValue != null ) {
mappingColumn.setDefaultValue( defaultValue );
}
if ( StringHelper.isNotEmpty( comment ) ) {
mappingColumn.setComment (comment );
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Binding column: %s", toString() );
}
@ -471,6 +485,7 @@ public class Ejb3Column {
public static Ejb3Column[] buildColumnFromAnnotation(
javax.persistence.Column[] anns,
org.hibernate.annotations.Formula formulaAnn,
Comment commentAnn,
Nullability nullability,
PropertyHolder propertyHolder,
PropertyData inferredData,
@ -479,6 +494,7 @@ public class Ejb3Column {
return buildColumnFromAnnotation(
anns,
formulaAnn,
commentAnn,
nullability,
propertyHolder,
inferredData,
@ -490,6 +506,7 @@ public class Ejb3Column {
public static Ejb3Column[] buildColumnFromAnnotation(
javax.persistence.Column[] anns,
org.hibernate.annotations.Formula formulaAnn,
Comment commentAnn,
Nullability nullability,
PropertyHolder propertyHolder,
PropertyData inferredData,
@ -525,6 +542,7 @@ public class Ejb3Column {
suffixForDefaultColumnName,
secondaryTables,
propertyHolder,
commentAnn,
nullability,
context
);
@ -601,6 +619,9 @@ public class Ejb3Column {
column.setNullable(
col.nullable()
); //TODO force to not null if available? This is a (bad) user choice.
if ( commentAnn != null ) {
column.setComment( commentAnn.value() );
}
column.setUnique( col.unique() );
column.setInsertable( col.insertable() );
column.setUpdatable( col.updatable() );
@ -676,12 +697,17 @@ public class Ejb3Column {
String suffixForDefaultColumnName,
Map<String, Join> secondaryTables,
PropertyHolder propertyHolder,
Comment comment,
Nullability nullability,
MetadataBuildingContext context) {
Ejb3Column column = new Ejb3Column();
Ejb3Column[] columns = new Ejb3Column[1];
columns[0] = column;
if ( comment != null ) {
column.setComment( comment.value() );
}
//not following the spec but more clean
if ( nullability != Nullability.FORCED_NULL
&& inferredData.getClassOrElement().isPrimitive()

View File

@ -17,6 +17,7 @@ import javax.persistence.PrimaryKeyJoinColumn;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinFormula;
import org.hibernate.annotations.common.reflection.XClass;
@ -98,6 +99,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
private Ejb3JoinColumn(
String sqlType,
String name,
String comment,
boolean nullable,
boolean unique,
boolean insertable,
@ -114,6 +116,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
setImplicit( isImplicit );
setSqlType( sqlType );
setLogicalColumnName( name );
setComment( comment );
setNullable( nullable );
setUnique( unique );
setInsertable( insertable );
@ -150,7 +153,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
}
else {
joinColumns[i] = buildJoinColumns(
new JoinColumn[] { join.column() }, mappedBy, joins, propertyHolder, propertyName, buildingContext
new JoinColumn[] { join.column() }, null, mappedBy, joins, propertyHolder, propertyName, buildingContext
)[0];
}
}
@ -181,18 +184,20 @@ public class Ejb3JoinColumn extends Ejb3Column {
public static Ejb3JoinColumn[] buildJoinColumns(
JoinColumn[] anns,
Comment comment,
String mappedBy,
Map<String, Join> joins,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
return buildJoinColumnsWithDefaultColumnSuffix(
anns, mappedBy, joins, propertyHolder, propertyName, "", buildingContext
anns, comment, mappedBy, joins, propertyHolder, propertyName, "", buildingContext
);
}
public static Ejb3JoinColumn[] buildJoinColumnsWithDefaultColumnSuffix(
JoinColumn[] anns,
Comment comment,
String mappedBy,
Map<String, Join> joins,
PropertyHolder propertyHolder,
@ -207,6 +212,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
return new Ejb3JoinColumn[] {
buildJoinColumn(
null,
comment,
mappedBy,
joins,
propertyHolder,
@ -222,6 +228,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
for (int index = 0; index < size; index++) {
result[index] = buildJoinColumn(
actualColumns[index],
comment,
mappedBy,
joins,
propertyHolder,
@ -239,6 +246,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
*/
private static Ejb3JoinColumn buildJoinColumn(
JoinColumn ann,
Comment comment,
String mappedBy, Map<String, Join> joins,
PropertyHolder propertyHolder,
String propertyName,
@ -252,6 +260,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
);
}
Ejb3JoinColumn joinColumn = new Ejb3JoinColumn();
joinColumn.setComment( comment != null ? comment.value() : null );
joinColumn.setBuildingContext( buildingContext );
joinColumn.setJoinAnnotation( ann, null );
if ( StringHelper.isEmpty( joinColumn.getLogicalColumnName() )
@ -376,6 +385,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
return new Ejb3JoinColumn(
sqlType,
name,
null,
false,
false,
true,
@ -395,6 +405,7 @@ public class Ejb3JoinColumn extends Ejb3Column {
return new Ejb3JoinColumn(
null,
defaultName,
null,
false,
false,
true,

View File

@ -72,6 +72,7 @@ public class IdBagBinder extends BagBinder {
Ejb3Column[] idColumns = Ejb3Column.buildColumnFromAnnotation(
collectionIdAnn.columns(),
null,
null,
Nullability.FORCED_NOT_NULL,
propertyHolder,
propertyData,

View File

@ -0,0 +1,76 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations.comment;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.util.Iterator;
import java.util.stream.StreamSupport;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Comment;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Table;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
/**
* @author Yanming Zhou
*/
public class CommentTest extends BaseUnitTestCase {
private static final String TABLE_NAME = "TestEntity";
private static final String TABLE_COMMENT = "I am table";
@Test
@TestForIssue(jiraKey = "HHH-4369")
public void testComments() {
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
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));
Iterator<Column> it = table.getColumnIterator();
while (it.hasNext()) {
Column col = it.next();
assertThat(col.getComment(), is("I am " + col.getName()));
}
}
@Entity(name = "Person")
@javax.persistence.Table(name = TABLE_NAME)
@org.hibernate.annotations.Table(comment = TABLE_COMMENT, appliesTo = TABLE_NAME)
public static class TestEntity {
@Id
@GeneratedValue
@Comment("I am id")
private Long id;
@Comment("I am name")
@javax.persistence.Column(length = 50)
private String name;
@ManyToOne
@JoinColumn(name = "other")
@Comment("I am other")
private TestEntity other;
}
}