HHH-18057 Support for JPA 3.2 column options

This commit is contained in:
Andrea Boriero 2024-05-11 09:06:40 +02:00 committed by Steve Ebersole
parent 79e7cc6f01
commit ee1c583d2e
15 changed files with 675 additions and 100 deletions

View File

@ -97,6 +97,8 @@ public class AnnotatedColumn {
private AnnotatedColumns parent; private AnnotatedColumns parent;
private String options;
public AnnotatedColumns getParent() { public AnnotatedColumns getParent() {
return parent; return parent;
} }
@ -263,6 +265,8 @@ public class AnnotatedColumn {
for ( CheckConstraint constraint : checkConstraints ) { for ( CheckConstraint constraint : checkConstraints ) {
mappingColumn.addCheckConstraint( constraint ); mappingColumn.addCheckConstraint( constraint );
} }
mappingColumn.setOptions( options );
// if ( isNotEmpty( comment ) ) { // if ( isNotEmpty( comment ) ) {
// mappingColumn.setComment( comment ); // mappingColumn.setComment( comment );
// } // }
@ -313,6 +317,7 @@ public class AnnotatedColumn {
mappingColumn.addCheckConstraint( constraint ); mappingColumn.addCheckConstraint( constraint );
} }
mappingColumn.setDefaultValue( defaultValue ); mappingColumn.setDefaultValue( defaultValue );
mappingColumn.setOptions( options );
if ( writeExpression != null ) { if ( writeExpression != null ) {
final int numberOfJdbcParams = StringHelper.count( writeExpression, '?' ); final int numberOfJdbcParams = StringHelper.count( writeExpression, '?' );
@ -806,6 +811,7 @@ public class AnnotatedColumn {
annotatedColumn.applyColumnDefault( inferredData, numberOfColumns ); annotatedColumn.applyColumnDefault( inferredData, numberOfColumns );
annotatedColumn.applyGeneratedAs( inferredData, numberOfColumns ); annotatedColumn.applyGeneratedAs( inferredData, numberOfColumns );
annotatedColumn.applyColumnCheckConstraint( column ); annotatedColumn.applyColumnCheckConstraint( column );
annotatedColumn.applyColumnOptions( column );
annotatedColumn.applyCheckConstraint( inferredData, numberOfColumns ); annotatedColumn.applyCheckConstraint( inferredData, numberOfColumns );
annotatedColumn.extractDataFromPropertyData( propertyHolder, inferredData ); annotatedColumn.extractDataFromPropertyData( propertyHolder, inferredData );
annotatedColumn.bind(); annotatedColumn.bind();
@ -1052,4 +1058,13 @@ public class AnnotatedColumn {
MetadataBuildingContext getBuildingContext() { MetadataBuildingContext getBuildingContext() {
return getParent().getBuildingContext(); return getParent().getBuildingContext();
} }
private void applyColumnOptions(AnnotationUsage<jakarta.persistence.Column> column) {
options = column.findAttributeValue( "options" );
}
void setOptions(String options){
this.options = options;
}
} }

View File

@ -75,6 +75,7 @@ public class AnnotatedDiscriminatorColumn extends AnnotatedColumn {
column.setLogicalColumnName( discriminatorColumn.getString( "name" ) ); column.setLogicalColumnName( discriminatorColumn.getString( "name" ) );
} }
column.setNullable( false ); column.setNullable( false );
column.setOptions( discriminatorColumn.getString( "options" ) );
} }
else { else {
discriminatorType = DiscriminatorType.STRING; discriminatorType = DiscriminatorType.STRING;

View File

@ -196,6 +196,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
setUpdatable( joinColumn.getBoolean( "updatable" ) ); setUpdatable( joinColumn.getBoolean( "updatable" ) );
setReferencedColumn( joinColumn.getString( "referencedColumnName" ) ); setReferencedColumn( joinColumn.getString( "referencedColumnName" ) );
applyColumnCheckConstraint( joinColumn ); applyColumnCheckConstraint( joinColumn );
setOptions( joinColumn.getString( "options" ) );
final String table = joinColumn.getString( "table" ); final String table = joinColumn.getString( "table" );
if ( table.isEmpty() ) { if ( table.isEmpty() ) {
@ -237,15 +238,18 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
final String columnName; final String columnName;
final String columnDefinition; final String columnDefinition;
final String referencedColumnName; final String referencedColumnName;
final String options;
if ( primaryKeyJoinColumn != null ) { if ( primaryKeyJoinColumn != null ) {
columnName = primaryKeyJoinColumn.getString( "name" ); columnName = primaryKeyJoinColumn.getString( "name" );
columnDefinition = primaryKeyJoinColumn.getString( "columnDefinition" ); columnDefinition = primaryKeyJoinColumn.getString( "columnDefinition" );
referencedColumnName = primaryKeyJoinColumn.getString( "referencedColumnName" ); referencedColumnName = primaryKeyJoinColumn.getString( "referencedColumnName" );
options = primaryKeyJoinColumn.getString( "options" );
} }
else { else {
columnName = joinColumn.getString( "name" ); columnName = joinColumn.getString( "name" );
columnDefinition = joinColumn.getString( "columnDefinition" ); columnDefinition = joinColumn.getString( "columnDefinition" );
referencedColumnName = joinColumn.getString( "referencedColumnName" ); referencedColumnName = joinColumn.getString( "referencedColumnName" );
options = joinColumn.getString( "options" );
} }
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer(); final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
@ -261,6 +265,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
// column.setPropertyHolder(propertyHolder); // column.setPropertyHolder(propertyHolder);
// column.setJoins(joins); // column.setJoins(joins);
// column.setContext( context ); // column.setContext( context );
column.setOptions( options );
column.setImplicit( false ); column.setImplicit( false );
column.setNullable( false ); column.setNullable( false );
column.setParent( parent ); column.setParent( parent );

View File

@ -647,12 +647,10 @@ public abstract class CollectionBinder {
} }
final List<AnnotationUsage<MapKeyJoinColumn>> mapKeyJoinColumns = property.getAnnotationUsage( MapKeyJoinColumns.class ).getList( "value" ); final List<AnnotationUsage<MapKeyJoinColumn>> mapKeyJoinColumns = property.getAnnotationUsage( MapKeyJoinColumns.class ).getList( "value" );
final List<AnnotationUsage<JoinColumn>> joinKeyColumns = CollectionHelper.arrayList( mapKeyJoinColumns.size() ); final List<AnnotationUsage<JoinColumn>> joinKeyColumns = CollectionHelper.arrayList( mapKeyJoinColumns.size() );
int index = 0;
for ( AnnotationUsage<MapKeyJoinColumn> mapKeyJoinColumn : mapKeyJoinColumns ) { for ( AnnotationUsage<MapKeyJoinColumn> mapKeyJoinColumn : mapKeyJoinColumns ) {
final MutableAnnotationUsage<JoinColumn> joinColumn final MutableAnnotationUsage<JoinColumn> joinColumn
= MapKeyJoinColumnDelegator.fromMapKeyJoinColumn( mapKeyJoinColumn, property, context ); = MapKeyJoinColumnDelegator.fromMapKeyJoinColumn( mapKeyJoinColumn, property, context );
joinKeyColumns.add( joinColumn ); joinKeyColumns.add( joinColumn );
index++;
} }
return joinKeyColumns; return joinKeyColumns;
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.boot.model.internal; package org.hibernate.boot.model.internal;
import java.lang.annotation.Annotation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -25,10 +24,8 @@ import org.hibernate.models.spi.MemberDetails;
import org.hibernate.models.spi.MutableAnnotationUsage; import org.hibernate.models.spi.MutableAnnotationUsage;
import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.SourceModelBuildingContext;
import jakarta.persistence.CheckConstraint;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection; import jakarta.persistence.ElementCollection;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinColumns; import jakarta.persistence.JoinColumns;
import jakarta.persistence.JoinTable; import jakarta.persistence.JoinTable;
@ -361,77 +358,4 @@ class ColumnsBuilder {
} }
} }
@SuppressWarnings("ClassExplicitlyAnnotation")
private static final class JoinColumnAdapter implements JoinColumn {
private final PrimaryKeyJoinColumn column;
public JoinColumnAdapter(PrimaryKeyJoinColumn column) {
this.column = column;
}
@Override
public String name() {
return column.name();
}
@Override
public String referencedColumnName() {
return column.referencedColumnName();
}
@Override
public boolean unique() {
return false;
}
@Override
public boolean nullable() {
return false;
}
@Override
public boolean insertable() {
return false;
}
@Override
public boolean updatable() {
return false;
}
@Override
public String columnDefinition() {
return column.columnDefinition();
}
@Override
public String table() {
return "";
}
@Override
public String options() {
return column.options();
}
@Override
public String comment() {
return "";
}
@Override
public ForeignKey foreignKey() {
return column.foreignKey();
}
@Override
public CheckConstraint[] check() {
return new CheckConstraint[0];
}
@Override
public Class<? extends Annotation> annotationType() {
return JoinColumn.class;
}
}
} }

View File

@ -114,6 +114,7 @@ public class IndexColumn extends AnnotatedColumn {
// column.setJoins( secondaryTables ); // column.setJoins( secondaryTables );
column.setInsertable( orderColumn.getBoolean( "insertable" ) ); column.setInsertable( orderColumn.getBoolean( "insertable" ) );
column.setUpdatable( orderColumn.getBoolean( "updatable" ) ); column.setUpdatable( orderColumn.getBoolean( "updatable" ) );
column.setOptions( orderColumn.getString( "options" ) );
// column.setContext( context ); // column.setContext( context );
// column.setPropertyHolder( propertyHolder ); // column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, secondaryTables, column, context ); createParent( propertyHolder, secondaryTables, column, context );

View File

@ -592,6 +592,10 @@ public class ManagedTypeProcessor {
xmlDocumentContext xmlDocumentContext
); );
XmlAnnotationHelper.applyPrimaryKeyJoinColumns(
jaxbEntity, classDetails, xmlDocumentContext
);
renderClass( classDetails, xmlDocumentContext ); renderClass( classDetails, xmlDocumentContext );
} }

View File

@ -52,6 +52,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbDiscriminatorColumnImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbDiscriminatorFormulaImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbDiscriminatorFormulaImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbElementCollectionImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbElementCollectionImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityListenerContainerImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityListenerContainerImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityOrMappedSuperclass; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityOrMappedSuperclass;
import org.hibernate.boot.jaxb.mapping.spi.JaxbGeneratedValueImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbGeneratedValueImpl;
@ -66,6 +67,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbNationalizedImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNaturalId; import org.hibernate.boot.jaxb.mapping.spi.JaxbNaturalId;
import org.hibernate.boot.jaxb.mapping.spi.JaxbNotFoundCapable; import org.hibernate.boot.jaxb.mapping.spi.JaxbNotFoundCapable;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute; import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPrimaryKeyJoinColumnImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbSchemaAware; import org.hibernate.boot.jaxb.mapping.spi.JaxbSchemaAware;
import org.hibernate.boot.jaxb.mapping.spi.JaxbSecondaryTableImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbSecondaryTableImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbSequenceGeneratorImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbSequenceGeneratorImpl;
@ -123,6 +125,7 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.IdClass; import jakarta.persistence.IdClass;
import jakarta.persistence.Index; import jakarta.persistence.Index;
import jakarta.persistence.Inheritance; import jakarta.persistence.Inheritance;
import jakarta.persistence.PrimaryKeyJoinColumns;
import jakarta.persistence.SecondaryTable; import jakarta.persistence.SecondaryTable;
import jakarta.persistence.SecondaryTables; import jakarta.persistence.SecondaryTables;
import jakarta.persistence.SequenceGenerator; import jakarta.persistence.SequenceGenerator;
@ -1539,4 +1542,30 @@ public class XmlAnnotationHelper {
values.add( tableAnn ); values.add( tableAnn );
} }
} }
public static void applyPrimaryKeyJoinColumns(
JaxbEntityImpl jaxbEntity,
MutableClassDetails classDetails,
XmlDocumentContext xmlDocumentContext) {
List<JaxbPrimaryKeyJoinColumnImpl> primaryKeyJoinColumns = jaxbEntity.getPrimaryKeyJoinColumns();
if ( CollectionHelper.isEmpty( primaryKeyJoinColumns ) ) {
return;
}
final SourceModelBuildingContext modelBuildingContext = xmlDocumentContext.getModelBuildingContext();
final MutableAnnotationUsage<PrimaryKeyJoinColumns> primaryKeyJoinColumnsAnnotationUsage = classDetails.replaceAnnotationUsage(
JpaAnnotations.PRIMARY_KEY_JOIN_COLUMN,
JpaAnnotations.PRIMARY_KEY_JOIN_COLUMNS,
modelBuildingContext
);
final ArrayList<Object> primaryKeyJoinColumnList = arrayList( primaryKeyJoinColumns.size() );
primaryKeyJoinColumnsAnnotationUsage.setAttributeValue( "value", primaryKeyJoinColumnList );
for ( JaxbPrimaryKeyJoinColumnImpl primaryKeyJoinColumn : primaryKeyJoinColumns ) {
primaryKeyJoinColumnList.add(
JoinColumnProcessing.createPrimaryKeyJoinColumnUsage( primaryKeyJoinColumn, xmlDocumentContext )
);
}
}
} }

View File

@ -194,28 +194,10 @@ public class JoinColumnProcessing {
final List<MutableAnnotationUsage<PrimaryKeyJoinColumn>> columnUsages = CollectionHelper.arrayList( jaxbJoinColumns.size() ); final List<MutableAnnotationUsage<PrimaryKeyJoinColumn>> columnUsages = CollectionHelper.arrayList( jaxbJoinColumns.size() );
jaxbJoinColumns.forEach( (jaxbJoinColumn) -> { jaxbJoinColumns.forEach(
final MutableAnnotationUsage<PrimaryKeyJoinColumn> columnUsage = (jaxbJoinColumn) ->
JpaAnnotations.PRIMARY_KEY_JOIN_COLUMN.createUsage( xmlDocumentContext.getModelBuildingContext() ); columnUsages.add( createPrimaryKeyJoinColumnUsage( jaxbJoinColumn, xmlDocumentContext ) )
columnUsages.add( columnUsage );
ColumnProcessing.applyColumnDetails(
jaxbJoinColumn,
(MutableAnnotationUsage<? extends Annotation>) columnUsage,
xmlDocumentContext
); );
XmlAnnotationHelper.applyOptionalAttribute(
columnUsage,
"referencedColumnName",
((JaxbColumnJoined) jaxbJoinColumn).getReferencedColumnName()
);
ForeignKeyProcessing.applyForeignKey(
( (JaxbColumnJoined) jaxbJoinColumn ).getForeignKey(),
(MutableAnnotationUsage<? extends Annotation>) columnUsage,
xmlDocumentContext
);
} );
tableAnn.setAttributeValue( tableAnn.setAttributeValue(
"pkJoinColumns", "pkJoinColumns",
@ -223,4 +205,30 @@ public class JoinColumnProcessing {
); );
} }
public static MutableAnnotationUsage<PrimaryKeyJoinColumn> createPrimaryKeyJoinColumnUsage(
JaxbPrimaryKeyJoinColumnImpl jaxbJoinColumn,
XmlDocumentContext xmlDocumentContext) {
final MutableAnnotationUsage<PrimaryKeyJoinColumn> columnUsage =
JpaAnnotations.PRIMARY_KEY_JOIN_COLUMN.createUsage( xmlDocumentContext.getModelBuildingContext() );
ColumnProcessing.applyColumnDetails(
jaxbJoinColumn,
(MutableAnnotationUsage<? extends Annotation>) columnUsage,
xmlDocumentContext
);
XmlAnnotationHelper.applyOptionalAttribute(
columnUsage,
"referencedColumnName",
((JaxbColumnJoined) jaxbJoinColumn ).getReferencedColumnName()
);
ForeignKeyProcessing.applyForeignKey(
( (JaxbColumnJoined) jaxbJoinColumn ).getForeignKey(),
(MutableAnnotationUsage<? extends Annotation>) columnUsage,
xmlDocumentContext
);
return columnUsage;
}
} }

View File

@ -80,6 +80,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
private Size columnSize; private Size columnSize;
private String collation; private String collation;
private java.util.List<CheckConstraint> checkConstraints = new ArrayList<>(); private java.util.List<CheckConstraint> checkConstraints = new ArrayList<>();
private String options;
public Column() { public Column() {
} }
@ -788,6 +789,14 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
return quoted ? name : name.toLowerCase( Locale.ROOT ); return quoted ? name : name.toLowerCase( Locale.ROOT );
} }
public String getOptions() {
return options;
}
public void setOptions(String options) {
this.options = options;
}
/** /**
* Shallow copy, the value is not copied * Shallow copy, the value is not copied
*/ */
@ -817,6 +826,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
copy.customWrite = customWrite; copy.customWrite = customWrite;
// copy.specializedTypeDeclaration = specializedTypeDeclaration; // copy.specializedTypeDeclaration = specializedTypeDeclaration;
copy.columnSize = columnSize; copy.columnSize = columnSize;
copy.options = options;
return copy; return copy;
} }
} }

View File

@ -10,6 +10,7 @@ import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.CheckConstraint; import org.hibernate.mapping.CheckConstraint;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Constraint; import org.hibernate.mapping.Constraint;
@ -111,6 +112,14 @@ class ColumnDefinitions {
appendColumnDefinition( statement, column, metadata, dialect ); appendColumnDefinition( statement, column, metadata, dialect );
appendComment( statement, column, dialect ); appendComment( statement, column, dialect );
appendConstraints( statement, column, table, dialect, context ); appendConstraints( statement, column, table, dialect, context );
appendOptions(statement, column, dialect);
}
private static void appendOptions(StringBuilder statement, Column column, Dialect dialect) {
final String options = column.getOptions();
if ( StringHelper.isNotEmpty( options ) ) {
statement.append( " " ).append( options );
}
} }
private static void appendConstraints( private static void appendConstraints(

View File

@ -0,0 +1,18 @@
package org.hibernate.orm.test.schemaupdate.columnoptions;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.PrimaryKeyJoinColumn;
import jakarta.persistence.PrimaryKeyJoinColumns;
import jakarta.persistence.Table;
@Entity
@Table(name = "ANOTHER_TEST_ENTITY")
@PrimaryKeyJoinColumns(
value = @PrimaryKeyJoinColumn(name = "joined_fk", options = ColumnOptionsTest.PRIMARY_KEY_JOIN_COLUMN_OPTIONS)
)
public class AnotherTestEntity extends TestEntity {
}

View File

@ -0,0 +1,333 @@
package org.hibernate.orm.test.schemaupdate.columnoptions;
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.JiraKey;
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;
@BaseUnitTest
@JiraKey("HHH-18057")
public class ColumnOptionsTest {
static final String COLUMN_NAME = "NAME";
static final String COLUMN_OPTIONS = "option_1";
static final String DISCRIMINATOR_COLUMN_NAME = "DISC_COLUMN";
static final String DISCRIMINATOR_COLUMN_OPTIONS = "option_2";
static final String PRIMARY_KEY_JOIN_COLUMN_NAME = "PRIMARY_KEY_COLUMN";
static final String PRIMARY_KEY_JOIN_COLUMN_OPTIONS = "option_3";
static final String JOIN_COLUMN_NAME = "JOIN_COLUMN";
static final String JOIN_COLUMN_OPTIONS = "option_4";
static final String ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME = "MAP_KEY_COLUMN";
static final String ELEMENT_COLLECTION_MAP_KEY_COLUMN_OPTIONS = "option_5";
static final String ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME = "MAP_KEY_JOIN_COLUMN";
static final String ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_OPTIONS = "option_6";
static final String ONE_TO_MANY_MAP_KEY_COLUMN_NAME = "MAP_KEY_COLUMN_2";
static final String ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS = "option_7";
static final String ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME = "MAP_KEY_JOIN_COLUMN_2";
static final String ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS = "option_8";
static final String MANY_TO_MANY_MAP_KEY_COLUMN_NAME = "MAP_KEY_COLUMN_3";
static final String MANY_TO_MANY_MAP_KEY_COLUMN_OPTIONS = "option_9";
static final String MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME = "MAP_KEY_JOIN_COLUMN_3";
static final String MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS = "option__10";
static final String ORDER_COLUMN_NAME = "ORDER_COLUMN";
static final String ORDER_COLUMN_OPTIONS = "option__11";
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, AnotherTestEntity.class );
assertTrue(
tableCreationStatementContainsOptions( output, COLUMN_NAME, COLUMN_OPTIONS ),
"Column " + COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
DISCRIMINATOR_COLUMN_NAME,
DISCRIMINATOR_COLUMN_OPTIONS
),
"DiscriminatorColumn " + DISCRIMINATOR_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions( output, JOIN_COLUMN_NAME, JOIN_COLUMN_OPTIONS ),
"JoinColumn " + JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME,
ELEMENT_COLLECTION_MAP_KEY_COLUMN_OPTIONS
),
"ElementCollection MapKeyColumn " + ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"OneToMany MapKeyColumn " + ONE_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
MANY_TO_MANY_MAP_KEY_COLUMN_NAME,
MANY_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"ManyToMany MapKeyColumn " + MANY_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"OneToMany MapKeyColumn " + ONE_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
PRIMARY_KEY_JOIN_COLUMN_NAME,
PRIMARY_KEY_JOIN_COLUMN_OPTIONS
),
"PrimaryKeyJoinColumn " + PRIMARY_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME,
ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"ElementCollection MapKeyJoinColumn " + ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"OneToMany MapKeyJoinColumn " + ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME,
MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"ManyToMany MapKeyJoinColumn " + MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ORDER_COLUMN_NAME,
ORDER_COLUMN_OPTIONS
),
"OrderColumn " + ORDER_COLUMN_NAME + " options have not been created "
);
}
@Test
public void testXmlMappingTableCommentAreCreated() throws Exception {
createSchema( "org/hibernate/orm/test/schemaupdate/columnoptions/TestEntity.xml" );
assertTrue(
tableCreationStatementContainsOptions( output, COLUMN_NAME, COLUMN_OPTIONS ),
"Column " + COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
DISCRIMINATOR_COLUMN_NAME,
DISCRIMINATOR_COLUMN_OPTIONS
),
"DiscriminatorColumn " + DISCRIMINATOR_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions( output, JOIN_COLUMN_NAME, JOIN_COLUMN_OPTIONS ),
"JoinColumn " + JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME,
ELEMENT_COLLECTION_MAP_KEY_COLUMN_OPTIONS
),
"ElementCollection MapKeyColumn " + ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"OneToMany MapKeyColumn " + ONE_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
MANY_TO_MANY_MAP_KEY_COLUMN_NAME,
MANY_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"ManyToMany MapKeyColumn " + MANY_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS
),
"OneToMany MapKeyColumn " + ONE_TO_MANY_MAP_KEY_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
PRIMARY_KEY_JOIN_COLUMN_NAME,
PRIMARY_KEY_JOIN_COLUMN_OPTIONS
),
"PrimaryKeyJoinColumn " + PRIMARY_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME,
ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"ElementCollection MapKeyJoinColumn " + ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME,
ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"OneToMany MapKeyJoinColumn " + ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME,
MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS
),
"ManyToMany MapKeyJoinColumn " + MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS + " options have not been created "
);
assertTrue(
tableCreationStatementContainsOptions(
output,
ORDER_COLUMN_NAME,
ORDER_COLUMN_OPTIONS
),
"OrderColumn " + ORDER_COLUMN_NAME + " options have not been created "
);
}
private static boolean tableCreationStatementContainsOptions(
File output,
String columnName,
String options) 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 ( statement.contains( options.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 )
.createOnly( EnumSet.of( TargetType.SCRIPT ), metadata );
}
}

View File

@ -0,0 +1,166 @@
package org.hibernate.orm.test.schemaupdate.columnoptions;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinColumns;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MapKeyColumn;
import jakarta.persistence.MapKeyJoinColumn;
import jakarta.persistence.MapKeyTemporal;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.Table;
import jakarta.persistence.TemporalType;
@Entity
@Table(name = "TEST_ENTITY")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = ColumnOptionsTest.DISCRIMINATOR_COLUMN_NAME, options = ColumnOptionsTest.DISCRIMINATOR_COLUMN_OPTIONS)
public class TestEntity {
@Id
private int id;
@Column(name = ColumnOptionsTest.COLUMN_NAME, options = ColumnOptionsTest.COLUMN_OPTIONS)
private String name;
@ManyToOne
@JoinColumns(
value = @JoinColumn(name = ColumnOptionsTest.JOIN_COLUMN_NAME, options = ColumnOptionsTest.JOIN_COLUMN_OPTIONS)
)
private TestEntity testEntity;
@MapKeyTemporal(TemporalType.DATE)
@ElementCollection
@MapKeyColumn(name = ColumnOptionsTest.ELEMENT_COLLECTION_MAP_KEY_COLUMN_NAME, options = ColumnOptionsTest.ELEMENT_COLLECTION_MAP_KEY_COLUMN_OPTIONS)
private Map<Date, Integer> colorPerDate = new HashMap<>();
@OneToMany
@MapKeyColumn(name = ColumnOptionsTest.ONE_TO_MANY_MAP_KEY_COLUMN_NAME, options = ColumnOptionsTest.ONE_TO_MANY_MAP_KEY_COLUMN_OPTIONS)
private Map<Date, TestEntity> testEntityMap = new HashMap<>();
@ManyToMany
@MapKeyColumn(name = ColumnOptionsTest.MANY_TO_MANY_MAP_KEY_COLUMN_NAME, options = ColumnOptionsTest.MANY_TO_MANY_MAP_KEY_COLUMN_OPTIONS)
private Map<Date, TestEntity> testEntityMap2 = new HashMap<>();
@ElementCollection
@CollectionTable(
name = "ELEMENT_COLLECTION_TABLE")
@MapKeyJoinColumn(name = ColumnOptionsTest.ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_NAME, insertable = false, options = ColumnOptionsTest.ELEMENT_COLLECTION_MAP_KEY_JOIN_COLUMN_OPTIONS)
private Map<AnotherTestEntity, String> stringMap = new HashMap<>();
@OneToMany
@JoinTable(name = "TEST_ENTITY_3")
@MapKeyJoinColumn(name = ColumnOptionsTest.ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME, options = ColumnOptionsTest.ONE_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS)
private Map<TestEntity, TestEntity> testEntityMap3 = new HashMap<>();
@ManyToMany
@JoinTable(name = "TEST_ENTITY_4")
@MapKeyJoinColumn(name = ColumnOptionsTest.MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_NAME, options = ColumnOptionsTest.MANY_TO_MANY_MAP_KEY_JOIN_COLUMN_OPTIONS)
private Map<TestEntity, TestEntity> testEntityMap4 = new HashMap<>();
@ElementCollection
@OrderColumn(name = ColumnOptionsTest.ORDER_COLUMN_NAME, options = ColumnOptionsTest.ORDER_COLUMN_OPTIONS)
int[] theNumbers;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TestEntity getTestEntity() {
return testEntity;
}
public void setTestEntity(TestEntity testEntity) {
this.testEntity = testEntity;
}
public Map<Date, Integer> getColorPerDate() {
return colorPerDate;
}
public void setColorPerDate(Map<Date, Integer> colorPerDate) {
this.colorPerDate = colorPerDate;
}
public Map<Date, TestEntity> getTestEntityMap() {
return testEntityMap;
}
public void setTestEntityMap(Map<Date, TestEntity> testEntityMap) {
this.testEntityMap = testEntityMap;
}
public Map<Date, TestEntity> getTestEntityMap2() {
return testEntityMap2;
}
public void setTestEntityMap2(Map<Date, TestEntity> testEntityMap2) {
this.testEntityMap2 = testEntityMap2;
}
public Map<AnotherTestEntity, String> getStringMap() {
return stringMap;
}
public void setStringMap(Map<AnotherTestEntity, String> stringMap) {
this.stringMap = stringMap;
}
public Map<TestEntity, TestEntity> getTestEntityMap3() {
return testEntityMap3;
}
public void setTestEntityMap3(Map<TestEntity, TestEntity> testEntityMap3) {
this.testEntityMap3 = testEntityMap3;
}
public Map<TestEntity, TestEntity> getTestEntityMap4() {
return testEntityMap4;
}
public void setTestEntityMap4(Map<TestEntity, TestEntity> testEntityMap4) {
this.testEntityMap4 = testEntityMap4;
}
public int[] getTheNumbers() {
return theNumbers;
}
public void setTheNumbers(int[] theNumbers) {
this.theNumbers = theNumbers;
}
// public AnotherTestEntity getAnotherTestEntity() {
// return anotherTestEntity;
// }
//
// public void setAnotherTestEntity(AnotherTestEntity anotherTestEntity) {
// this.anotherTestEntity = anotherTestEntity;
// }
}

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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>.
-->
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping" version="3.2">
<package>org.hibernate.orm.test.schemaupdate.columnoptions</package>
<entity class="TestEntity" metadata-complete="true">
<table name="PRIMARY_TABLE" options="option_1"/>
<inheritance strategy="JOINED"/>
<discriminator-column name="DISC_COLUMN" options="option_2"/>
<attributes>
<id name="id"/>
<basic name="name">
<column name="NAME_COLUMN" options="option_1"/>
</basic>
<many-to-one name="testEntity">
<join-column name="JOIN_COLUMN" options="option_4"/>
</many-to-one>
<one-to-many name="testEntityMap">
<map-key-column name="MAP_KEY_COLUMN_2" options="option_7"/>
</one-to-many>
<one-to-many name="testEntityMap3">
<map-key-join-column name="MAP_KEY_JOIN_COLUMN_2" options="option_8"/>
<join-table name="TEST_ENTITY_3"/>
</one-to-many>
<many-to-many name="testEntityMap2">
<map-key-column name="MAP_KEY_COLUMN_3" options="option_9"/>
</many-to-many>
<many-to-many name="testEntityMap4">
<map-key-join-column name="MAP_KEY_JOIN_COLUMN_3" options="option__10"/>
<join-table name="TEST_ENTITY_4"/>
</many-to-many>
<element-collection name="colorPerDate">
<map-key-temporal>DATE</map-key-temporal>
<map-key-column name="MAP_KEY_COLUMN" options="option_5"/>
</element-collection>
<element-collection name="stringMap">
<map-key-join-column name="MAP_KEY_JOIN_COLUMN" options="option_6"/>
<collection-table name="ELEMENT_COLLECTION_TABLE"/>
</element-collection>
<element-collection name="theNumbers">
<order-column name="ORDER_COLUMN" options="option__11"/>
</element-collection>
</attributes>
</entity>
<entity class="AnotherTestEntity" metadata-complete="true">
<table name="ANOTHER_TEST_ENTITY"/>
<primary-key-join-column name="joined_fk" options="option_3"/>
</entity>
</entity-mappings>