finally move context + joins from AnnotatedColumn

This commit is contained in:
Gavin King 2022-10-31 11:52:46 +01:00
parent 18003b92dc
commit e4c1d493e3
23 changed files with 650 additions and 697 deletions

View File

@ -6,10 +6,10 @@
*/
package org.hibernate.cfg;
import java.util.List;
import java.util.Map;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.ColumnDefault;
@ -65,13 +65,10 @@ public class AnnotatedColumn {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AnnotatedColumn.class.getName());
private MetadataBuildingContext context;
private Column mappingColumn;
private boolean insertable = true;
private boolean updatable = true;
private String explicitTableName; // the JPA @Column annotation lets you specify a table name
protected Map<String, Join> joins;
private boolean isImplicit;
public String sqlType;
private Long length;
@ -94,7 +91,12 @@ public class AnnotatedColumn {
private AnnotatedColumns parent;
void setParent(AnnotatedColumns parent) {
public AnnotatedColumns getParent() {
return parent;
}
public void setParent(AnnotatedColumns parent) {
parent.addColumn( this );
this.parent = parent;
}
@ -154,14 +156,6 @@ public class AnnotatedColumn {
this.updatable = updatable;
}
protected MetadataBuildingContext getBuildingContext() {
return context;
}
public void setBuildingContext(MetadataBuildingContext context) {
this.context = context;
}
public void setImplicit(boolean implicit) {
isImplicit = implicit;
}
@ -337,21 +331,21 @@ public class AnnotatedColumn {
private String processColumnName(String columnName, boolean applyNamingStrategy) {
if ( applyNamingStrategy ) {
final Database database = context.getMetadataCollector().getDatabase();
return context.getBuildingOptions().getPhysicalNamingStrategy()
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
return getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy()
.toPhysicalColumnName( database.toIdentifier( columnName ), database.getJdbcEnvironment() )
.render( database.getDialect() );
}
else {
return context.getObjectNameNormalizer().toDatabaseIdentifierText( columnName );
return getBuildingContext().getObjectNameNormalizer().toDatabaseIdentifierText( columnName );
}
}
private String inferColumnName(String propertyName) {
final Database database = context.getMetadataCollector().getDatabase();
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
final ImplicitNamingStrategy implicitNamingStrategy = context.getBuildingOptions().getImplicitNamingStrategy();
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
final ObjectNameNormalizer normalizer = getBuildingContext().getObjectNameNormalizer();
final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy();
Identifier implicitName = normalizer.normalizeIdentifierQuoting(
implicitNamingStrategy.determineBasicColumnName(
@ -373,7 +367,7 @@ public class AnnotatedColumn {
@Override
public MetadataBuildingContext getBuildingContext() {
return context;
return AnnotatedColumn.this.getBuildingContext();
}
}
)
@ -387,7 +381,7 @@ public class AnnotatedColumn {
);
}
return context.getBuildingOptions().getPhysicalNamingStrategy()
return getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy()
.toPhysicalColumnName( implicitName, database.getJdbcEnvironment() )
.render( database.getDialect() );
}
@ -409,20 +403,14 @@ public class AnnotatedColumn {
}
public void setNullable(boolean nullable) {
this.nullable = nullable;
if ( mappingColumn != null ) {
mappingColumn.setNullable( nullable );
}
else {
this.nullable = nullable;
}
}
public void setJoins(Map<String, Join> joins) {
this.joins = joins;
}
public PropertyHolder getPropertyHolder() {
return parent.getPropertyHolder();
return getParent().getPropertyHolder();
}
protected void setMappingColumn(Column mappingColumn) {
@ -436,8 +424,8 @@ public class AnnotatedColumn {
}
else {
final Table table = value.getTable();
if ( parent != null ) {
parent.setTableInternal( table );
if ( getParent() != null ) {
getParent().setTableInternal( table );
}
getMappingColumn().setValue( value );
value.addColumn( getMappingColumn(), insertable, updatable );
@ -452,9 +440,9 @@ public class AnnotatedColumn {
logicalColumnName = this.logicalColumnName;
}
else {
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
final Database database = context.getMetadataCollector().getDatabase();
final ImplicitNamingStrategy implicitNamingStrategy = context.getBuildingOptions()
final ObjectNameNormalizer normalizer = getBuildingContext().getObjectNameNormalizer();
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions()
.getImplicitNamingStrategy();
final Identifier implicitName = normalizer.normalizeIdentifierQuoting(
@ -472,14 +460,14 @@ public class AnnotatedColumn {
@Override
public MetadataBuildingContext getBuildingContext() {
return context;
return AnnotatedColumn.this.getBuildingContext();
}
}
)
);
logicalColumnName = implicitName.render( database.getDialect() );
}
context.getMetadataCollector().addColumnNameBinding( value.getTable(), logicalColumnName, getMappingColumn() );
getBuildingContext().getMetadataCollector().addColumnNameBinding( value.getTable(), logicalColumnName, getMappingColumn() );
}
/**
@ -490,38 +478,17 @@ public class AnnotatedColumn {
* @throws AnnotationException missing secondary table
*/
public Table getTable() {
return parent.getTable();
return getParent().getTable();
}
//TODO: move to AnnotatedColumns
public boolean isSecondary() {
if ( getPropertyHolder() == null ) {
throw new AssertionFailure( "Should not call isSecondary() on column w/o persistent class defined" );
}
return isNotEmpty( explicitTableName )
&& !getPropertyHolder().getTable().getName().equals( explicitTableName );
return getParent().isSecondary();
}
//TODO: move to AnnotatedColumns
public Join getJoin() {
Join join = joins.get( explicitTableName );
if ( join == null ) {
// annotation binding seems to use logical and physical naming somewhat inconsistently...
final String physicalTableName = getBuildingContext().getMetadataCollector()
.getPhysicalTableName( explicitTableName );
if ( physicalTableName != null ) {
join = joins.get( physicalTableName );
}
}
if ( join == null ) {
throw new AnnotationException(
"Secondary table '" + explicitTableName + "' for property '" + getPropertyHolder().getClassName()
+ "' is not declared (use '@SecondaryTable' to declare the secondary table)"
);
}
return join;
return getParent().getJoin();
}
public void forceNotNull() {
@ -531,6 +498,7 @@ public class AnnotatedColumn {
"likely a formula"
);
}
nullable = false;
mappingColumn.setNullable( false );
}
@ -669,16 +637,18 @@ public class AnnotatedColumn {
MetadataBuildingContext context) {
if ( formulaAnn != null ) {
AnnotatedColumn formulaColumn = new AnnotatedColumn();
final AnnotatedColumns parent = new AnnotatedColumns();
parent.setPropertyHolder( propertyHolder );
parent.setBuildingContext( context );
parent.setJoins( secondaryTables ); //unnecessary
final AnnotatedColumn formulaColumn = new AnnotatedColumn();
formulaColumn.setFormula( formulaAnn.value() );
formulaColumn.setImplicit( false );
formulaColumn.setBuildingContext( context );
// formulaColumn.setBuildingContext( context );
// formulaColumn.setPropertyHolder( propertyHolder );
final AnnotatedColumns result = new AnnotatedColumns();
result.setPropertyHolder( propertyHolder );
result.setColumns( new AnnotatedColumn[] {formulaColumn} );
formulaColumn.setParent( parent );
formulaColumn.bind();
return result;
return parent;
}
else {
final jakarta.persistence.Column[] actualColumns = overrideColumns( columns, propertyHolder, inferredData );
@ -740,10 +710,11 @@ public class AnnotatedColumn {
Map<String, Join> secondaryTables,
MetadataBuildingContext context,
jakarta.persistence.Column[] actualCols) {
final int length = actualCols.length;
final AnnotatedColumn[] columns = new AnnotatedColumn[length];
for ( int index = 0; index < length; index++ ) {
final jakarta.persistence.Column column = actualCols[index];
final AnnotatedColumns parent = new AnnotatedColumns();
parent.setPropertyHolder( propertyHolder );
parent.setJoins( secondaryTables );
parent.setBuildingContext( context );
for ( jakarta.persistence.Column column : actualCols ) {
final Database database = context.getMetadataCollector().getDatabase();
final String sqlType = getSqlType( context, column );
final String tableName = getTableName( column, database );
@ -752,24 +723,20 @@ public class AnnotatedColumn {
// .toIdentifier( column.table() );
// final Identifier physicalName = physicalNamingStrategy.toPhysicalTableName( logicalName );
// tableName = physicalName.render( database.getDialect() );
columns[index] = buildColumn(
buildColumn(
comment,
propertyHolder,
inferredData,
suffixForDefaultColumnName,
secondaryTables,
context,
length,
parent,
actualCols.length,
database,
column,
sqlType,
tableName
);
}
final AnnotatedColumns result = new AnnotatedColumns();
result.setPropertyHolder( propertyHolder );
result.setColumns( columns );
return result;
return parent;
}
private static String getTableName(jakarta.persistence.Column column, Database database) {
@ -787,42 +754,39 @@ public class AnnotatedColumn {
PropertyHolder propertyHolder,
PropertyData inferredData,
String suffixForDefaultColumnName,
Map<String, Join> secondaryTables,
MetadataBuildingContext context,
int length,
AnnotatedColumns parent,
int numberOfColumns,
Database database,
jakarta.persistence.Column col,
jakarta.persistence.Column column,
String sqlType,
String tableName) {
final AnnotatedColumn column = new AnnotatedColumn();
column.setLogicalColumnName( getLogicalColumnName( inferredData, suffixForDefaultColumnName, database, col ) );
column.setImplicit( false );
column.setSqlType(sqlType);
column.setLength( (long) col.length() );
column.setPrecision( col.precision() );
column.setScale( col.scale() );
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );
column.setNullable( col.nullable() ); //TODO force to not null if available? This is a (bad) user choice.
final String columnName = getLogicalColumnName( inferredData, suffixForDefaultColumnName, database, column );
final AnnotatedColumn annotatedColumn = new AnnotatedColumn();
annotatedColumn.setLogicalColumnName( columnName );
annotatedColumn.setImplicit( false );
annotatedColumn.setSqlType( sqlType );
annotatedColumn.setLength( (long) column.length() );
annotatedColumn.setPrecision( column.precision() );
annotatedColumn.setScale( column.scale() );
// annotatedColumn.setPropertyHolder( propertyHolder );
annotatedColumn.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );
annotatedColumn.setNullable( column.nullable() ); //TODO force to not null if available? This is a (bad) user choice.
if ( comment != null ) {
column.setComment( comment.value() );
annotatedColumn.setComment( comment.value() );
}
column.setUnique( col.unique() );
column.setInsertable( col.insertable() );
column.setUpdatable( col.updatable() );
column.setExplicitTableName( tableName );
column.setJoins( secondaryTables );
column.setBuildingContext( context );
column.applyColumnDefault( inferredData, length );
column.applyGeneratedAs( inferredData, length );
column.applyCheckConstraint( inferredData, length );
column.extractDataFromPropertyData( propertyHolder, inferredData );
AnnotatedColumns temp = new AnnotatedColumns();
temp.setPropertyHolder( propertyHolder );
temp.setColumns( new AnnotatedColumn[] { column } );
column.bind();
return column;
annotatedColumn.setUnique( column.unique() );
annotatedColumn.setInsertable( column.insertable() );
annotatedColumn.setUpdatable( column.updatable() );
annotatedColumn.setExplicitTableName( tableName );
// annotatedColumn.setJoins( secondaryTables );
// annotatedColumn.setBuildingContext( context );
annotatedColumn.setParent( parent );
annotatedColumn.applyColumnDefault( inferredData, numberOfColumns );
annotatedColumn.applyGeneratedAs( inferredData, numberOfColumns );
annotatedColumn.applyCheckConstraint( inferredData, numberOfColumns );
annotatedColumn.extractDataFromPropertyData( propertyHolder, inferredData );
annotatedColumn.bind();
return annotatedColumn;
}
private static String getLogicalColumnName(
@ -843,9 +807,10 @@ public class AnnotatedColumn {
}
private void applyColumnDefault(PropertyData inferredData, int length) {
final XProperty xProperty = inferredData.getProperty();
if ( xProperty != null ) {
final ColumnDefault columnDefault = getOverridableAnnotation( xProperty, ColumnDefault.class, context );
final XProperty property = inferredData.getProperty();
if ( property != null ) {
final ColumnDefault columnDefault =
getOverridableAnnotation( property, ColumnDefault.class, getBuildingContext() );
if ( columnDefault != null ) {
if ( length!=1 ) {
throw new MappingException("@ColumnDefault may only be applied to single-column mappings");
@ -859,9 +824,10 @@ public class AnnotatedColumn {
}
private void applyGeneratedAs(PropertyData inferredData, int length) {
final XProperty xProperty = inferredData.getProperty();
if ( xProperty != null ) {
final GeneratedColumn generatedColumn = getOverridableAnnotation( xProperty, GeneratedColumn.class, context );
final XProperty property = inferredData.getProperty();
if ( property != null ) {
final GeneratedColumn generatedColumn =
getOverridableAnnotation( property, GeneratedColumn.class, getBuildingContext() );
if ( generatedColumn != null ) {
if (length!=1) {
throw new MappingException("@GeneratedColumn may only be applied to single-column mappings");
@ -875,9 +841,9 @@ public class AnnotatedColumn {
}
private void applyCheckConstraint(PropertyData inferredData, int length) {
final XProperty xProperty = inferredData.getProperty();
if ( xProperty != null ) {
final Check check = getOverridableAnnotation( xProperty, Check.class, context );
final XProperty property = inferredData.getProperty();
if ( property != null ) {
final Check check = getOverridableAnnotation( property, Check.class, getBuildingContext() );
if ( check != null ) {
if (length!=1) {
throw new MappingException("@Check may only be applied to single-column mappings (use a table-level @Check)");
@ -928,29 +894,11 @@ public class AnnotatedColumn {
Comment comment,
Nullability nullability,
MetadataBuildingContext context) {
final AnnotatedColumns result = new AnnotatedColumns();
result.setPropertyHolder( propertyHolder );
final AnnotatedColumn column = bindImplicitColumn(
inferredData,
suffixForDefaultColumnName,
secondaryTables,
propertyHolder,
comment,
nullability,
context
);
result.setColumns( new AnnotatedColumn[] { column } );
return result;
}
private static AnnotatedColumn bindImplicitColumn(
PropertyData inferredData,
String suffixForDefaultColumnName,
Map<String, Join> secondaryTables,
PropertyHolder propertyHolder,
Comment comment,
Nullability nullability,
MetadataBuildingContext context) {
final AnnotatedColumns columns = new AnnotatedColumns();
columns.setPropertyHolder( propertyHolder );
columns.setBuildingContext( context );
columns.setJoins( secondaryTables );
columns.setPropertyHolder( propertyHolder );
final AnnotatedColumn column = new AnnotatedColumn();
if ( comment != null ) {
column.setComment( comment.value() );
@ -964,45 +912,45 @@ public class AnnotatedColumn {
final String propertyName = inferredData.getPropertyName();
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setJoins( secondaryTables );
column.setBuildingContext( context );
// column.setJoins( secondaryTables );
// column.setBuildingContext( context );
// property name + suffix is an "explicit" column name
boolean implicit = isEmpty( suffixForDefaultColumnName );
final boolean implicit = isEmpty( suffixForDefaultColumnName );
if ( !implicit ) {
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
}
column.setImplicit( implicit );
column.setParent( columns );
column.applyColumnDefault( inferredData, 1 );
column.applyGeneratedAs( inferredData, 1 );
column.applyCheckConstraint( inferredData, 1 );
column.extractDataFromPropertyData( propertyHolder, inferredData );
AnnotatedColumns temp = new AnnotatedColumns();
temp.setPropertyHolder( propertyHolder );
temp.setColumns( new AnnotatedColumn[] { column } );
column.bind();
return column;
return columns;
}
public static void checkPropertyConsistency(AnnotatedColumn[] columns, String propertyName) {
if ( columns.length > 1 ) {
for (int currentIndex = 1; currentIndex < columns.length; currentIndex++) {
if ( !columns[currentIndex].isFormula() && !columns[currentIndex - 1].isFormula() ) {
if ( columns[currentIndex].isNullable() != columns[currentIndex - 1].isNullable() ) {
public static void checkPropertyConsistency(List<AnnotatedColumn> columns, String propertyName) {
if ( columns.size() > 1 ) {
for ( int currentIndex = 1; currentIndex < columns.size(); currentIndex++ ) {
final AnnotatedColumn current = columns.get( currentIndex );
final AnnotatedColumn previous = columns.get( currentIndex - 1 );
if ( !current.isFormula() && !previous.isFormula() ) {
if ( current.isNullable() != previous.isNullable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix nullable with 'not null'"
);
}
if ( columns[currentIndex].isInsertable() != columns[currentIndex - 1].isInsertable() ) {
if ( current.isInsertable() != previous.isInsertable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix insertable with 'insertable=false'"
);
}
if ( columns[currentIndex].isUpdatable() != columns[currentIndex - 1].isUpdatable() ) {
if ( current.isUpdatable() != previous.isUpdatable() ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix updatable with 'updatable=false'"
);
}
if ( !columns[currentIndex].getTable().equals( columns[currentIndex - 1].getTable() ) ) {
if ( !current.getExplicitTableName().equals( previous.getExplicitTableName() ) ) {
throw new AnnotationException(
"Column mappings for property '" + propertyName + "' mix distinct secondary tables"
);
@ -1020,23 +968,23 @@ public class AnnotatedColumn {
void addIndex(String indexName, boolean inSecondPass) {
final IndexOrUniqueKeySecondPass secondPass =
new IndexOrUniqueKeySecondPass( indexName, this, context, false );
new IndexOrUniqueKeySecondPass( indexName, this, getBuildingContext(), false );
if ( inSecondPass ) {
secondPass.doSecondPass( context.getMetadataCollector().getEntityBindingMap() );
secondPass.doSecondPass( getBuildingContext().getMetadataCollector().getEntityBindingMap() );
}
else {
context.getMetadataCollector().addSecondPass( secondPass );
getBuildingContext().getMetadataCollector().addSecondPass( secondPass );
}
}
void addUniqueKey(String uniqueKeyName, boolean inSecondPass) {
final IndexOrUniqueKeySecondPass secondPass =
new IndexOrUniqueKeySecondPass( uniqueKeyName, this, context, true );
new IndexOrUniqueKeySecondPass( uniqueKeyName, this, getBuildingContext(), true );
if ( inSecondPass ) {
secondPass.doSecondPass( context.getMetadataCollector().getEntityBindingMap() );
secondPass.doSecondPass( getBuildingContext().getMetadataCollector().getEntityBindingMap() );
}
else {
context.getMetadataCollector().addSecondPass( secondPass );
getBuildingContext().getMetadataCollector().addSecondPass( secondPass );
}
}
@ -1056,4 +1004,8 @@ public class AnnotatedColumn {
string.append( ")" );
return string.toString();
}
MetadataBuildingContext getBuildingContext() {
return getParent().getBuildingContext();
}
}

View File

@ -1,7 +1,19 @@
package org.hibernate.cfg;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.Table;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static java.util.Collections.unmodifiableList;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/**
* A list of columns that are mapped to a single Java property
* or field. This is a slightly uncomfortable abstraction here,
@ -17,21 +29,14 @@ import org.hibernate.mapping.Table;
* @author Gavin King
*/
public class AnnotatedColumns {
private AnnotatedColumn[] columns;
private final List<AnnotatedColumn> columns = new ArrayList<>();
private Table table;
private PropertyHolder propertyHolder;
private Map<String, Join> joins = Collections.emptyMap();
private MetadataBuildingContext buildingContext;
public void setColumns(AnnotatedColumn[] columns) {
this.columns = columns;
if ( columns != null ) {
for ( AnnotatedColumn column : columns ) {
column.setParent( this );
}
}
}
public AnnotatedColumn[] getColumns() {
return columns;
public List<AnnotatedColumn> getColumns() {
return unmodifiableList( columns );
}
public PropertyHolder getPropertyHolder() {
@ -42,6 +47,49 @@ public class AnnotatedColumns {
this.propertyHolder = propertyHolder;
}
public void setBuildingContext(MetadataBuildingContext buildingContext) {
this.buildingContext = buildingContext;
}
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
}
public void setJoins(Map<String, Join> joins) {
this.joins = joins;
}
public Join getJoin() {
final AnnotatedColumn firstColumn = columns.get(0);
final String explicitTableName = firstColumn.getExplicitTableName();
Join join = joins.get( explicitTableName );
if ( join == null ) {
// annotation binding seems to use logical and physical naming somewhat inconsistently...
final String physicalTableName = getBuildingContext().getMetadataCollector()
.getPhysicalTableName( explicitTableName );
if ( physicalTableName != null ) {
join = joins.get( physicalTableName );
}
}
if ( join == null ) {
throw new AnnotationException(
"Secondary table '" + explicitTableName + "' for property '" + getPropertyHolder().getClassName()
+ "' is not declared (use '@SecondaryTable' to declare the secondary table)"
);
}
return join;
}
public boolean isSecondary() {
if ( getPropertyHolder() == null ) {
throw new AssertionFailure( "Should not call isSecondary() on column w/o persistent class defined" );
}
final AnnotatedColumn firstColumn = columns.get(0);
final String explicitTableName = firstColumn.getExplicitTableName();
return isNotEmpty( explicitTableName )
&& !getPropertyHolder().getTable().getName().equals( explicitTableName );
}
public Table getTable() {
if ( table != null ) {
return table;
@ -50,10 +98,8 @@ public class AnnotatedColumns {
// all the columns have to be mapped to the same table
// even though at the annotation level it looks like
// they could each specify a different table
final AnnotatedColumn firstColumn = columns[0];
return firstColumn.isSecondary()
? firstColumn.getJoin().getTable()
: firstColumn.getPropertyHolder().getTable();
final AnnotatedColumn firstColumn = columns.get(0);
return firstColumn.isSecondary() ? getJoin().getTable() : getPropertyHolder().getTable();
}
}
@ -65,4 +111,8 @@ public class AnnotatedColumns {
void setTableInternal(Table table) {
this.table = table;
}
public void addColumn(AnnotatedColumn child) {
columns.add( child );
}
}

View File

@ -49,8 +49,10 @@ public class AnnotatedDiscriminatorColumn extends AnnotatedColumn {
DiscriminatorColumn discriminatorColumn,
DiscriminatorFormula discriminatorFormula,
MetadataBuildingContext context) {
final AnnotatedColumns parent = new AnnotatedColumns();
parent.setBuildingContext( context );
final AnnotatedDiscriminatorColumn column = new AnnotatedDiscriminatorColumn();
column.setBuildingContext( context );
// column.setContext( context );
if ( discriminatorFormula != null ) {
column.setImplicit( false );
column.setFormula( discriminatorFormula.value() );
@ -69,31 +71,32 @@ public class AnnotatedDiscriminatorColumn extends AnnotatedColumn {
column.setImplicit( true );
}
setDiscriminatorType( type, discriminatorColumn, column );
column.setParent( parent );
column.bind();
return column;
}
private static void setDiscriminatorType(
DiscriminatorType type,
DiscriminatorColumn discAnn,
AnnotatedDiscriminatorColumn discriminatorColumn) {
DiscriminatorColumn discriminatorColumn,
AnnotatedDiscriminatorColumn column) {
if ( type == null ) {
discriminatorColumn.setDiscriminatorTypeName( "string" );
column.setDiscriminatorTypeName( "string" );
}
else {
switch ( type ) {
case CHAR:
discriminatorColumn.setDiscriminatorTypeName( "character" );
discriminatorColumn.setImplicit( false );
column.setDiscriminatorTypeName( "character" );
column.setImplicit( false );
break;
case INTEGER:
discriminatorColumn.setDiscriminatorTypeName( "integer" );
discriminatorColumn.setImplicit( false );
column.setDiscriminatorTypeName( "integer" );
column.setImplicit( false );
break;
case STRING:
discriminatorColumn.setDiscriminatorTypeName( "string" );
if ( discAnn != null ) {
discriminatorColumn.setLength( (long) discAnn.length() );
column.setDiscriminatorTypeName( "string" );
if ( discriminatorColumn != null ) {
column.setLength( (long) discriminatorColumn.length() );
}
break;
default:

View File

@ -7,7 +7,6 @@
package org.hibernate.cfg;
import java.util.List;
import java.util.Map;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.PrimaryKeyJoinColumn;
@ -54,7 +53,6 @@ import static org.hibernate.internal.util.StringHelper.unquote;
public class AnnotatedJoinColumn extends AnnotatedColumn {
private String referencedColumn;
private AnnotatedJoinColumns parent;
// due to @AnnotationOverride overriding rules,
// we don't want the constructor to be public
@ -82,42 +80,32 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
static AnnotatedJoinColumn buildJoinColumn(
JoinColumn joinColumn,
String mappedBy,
Map<String, Join> joins,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
String propertyName) {
final String path = qualify( propertyHolder.getPath(), propertyName );
final JoinColumn[] overriddes = propertyHolder.getOverriddenJoinColumn( path );
if ( overriddes != null ) {
final JoinColumn[] overrides = propertyHolder.getOverriddenJoinColumn( path );
if ( overrides != null ) {
//TODO: relax this restriction
throw new AnnotationException("Property '" + path
+ "' overrides mapping specified using '@JoinColumnOrFormula'");
}
return buildJoinColumn(
joinColumn,
null,
mappedBy,
joins,
propertyHolder,
propertyName,
"",
buildingContext
);
return buildJoinColumn( joinColumn, null, mappedBy, parent, propertyHolder, propertyName, "" );
}
public static AnnotatedJoinColumn buildJoinFormula(
JoinFormula joinFormula,
Map<String, Join> joins,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
String propertyName) {
final AnnotatedJoinColumn formulaColumn = new AnnotatedJoinColumn();
formulaColumn.setFormula( joinFormula.value() );
formulaColumn.setReferencedColumn( joinFormula.referencedColumnName() );
formulaColumn.setBuildingContext( buildingContext );
// formulaColumn.setContext( buildingContext );
// formulaColumn.setPropertyHolder( propertyHolder );
formulaColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
formulaColumn.setJoins( joins );
// formulaColumn.setJoins( joins );
formulaColumn.setParent( parent );
formulaColumn.bind();
return formulaColumn;
}
@ -126,11 +114,10 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
JoinColumn joinColumn,
Comment comment,
String mappedBy,
Map<String, Join> joins,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
String defaultColumnSuffix,
MetadataBuildingContext context) {
String defaultColumnSuffix) {
if ( joinColumn != null ) {
if ( !isEmptyOrNullAnnotationValue( mappedBy ) ) {
throw new AnnotationException(
@ -138,44 +125,44 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
+ "' is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'"
);
}
return explicitJoinColumn( joinColumn, comment, joins, propertyHolder, propertyName, defaultColumnSuffix, context );
return explicitJoinColumn( joinColumn, comment, parent, propertyHolder, propertyName, defaultColumnSuffix );
}
else {
return implicitJoinColumn( joins, propertyHolder, propertyName, defaultColumnSuffix, context );
return implicitJoinColumn( parent, propertyHolder, propertyName, defaultColumnSuffix );
}
}
private static AnnotatedJoinColumn explicitJoinColumn(
JoinColumn joinColumn,
Comment comment,
Map<String, Join> joins,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
String defaultColumnSuffix,
MetadataBuildingContext context) {
String defaultColumnSuffix) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setComment( comment != null ? comment.value() : null );
column.setBuildingContext( context );
column.setJoinAnnotation(joinColumn, null );
// column.setContext( context );
// column.setJoins( joins );
// column.setPropertyHolder( propertyHolder );
if ( isEmpty( column.getLogicalColumnName() ) && isNotEmpty( defaultColumnSuffix ) ) {
column.setLogicalColumnName( propertyName + defaultColumnSuffix );
}
column.setJoins( joins );
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setImplicit( false );
column.setParent( parent );
column.applyJoinAnnotation( joinColumn, null );
column.bind();
return column;
}
private static AnnotatedJoinColumn implicitJoinColumn(
Map<String, Join> joins,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
String defaultColumnSuffix,
MetadataBuildingContext context) {
String defaultColumnSuffix) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setJoins( joins );
// column.setContext( context );
// column.setJoins( joins );
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
// property name + suffix is an "explicit" column name
@ -186,14 +173,14 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
else {
column.setImplicit( true );
}
column.setBuildingContext( context );
column.setParent( parent );
column.bind();
return column;
}
// TODO default name still useful in association table
public void setJoinAnnotation(JoinColumn joinColumn, String defaultName) {
public void applyJoinAnnotation(JoinColumn joinColumn, String defaultName) {
if ( joinColumn == null ) {
setImplicit( true );
}
@ -233,21 +220,19 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
PrimaryKeyJoinColumn primaryKeyJoinColumn,
JoinColumn joinColumn,
Value identifier,
Map<String, Join> joins,
PropertyHolder propertyHolder,
AnnotatedJoinColumns parent,
MetadataBuildingContext context) {
final String defaultColumnName = context.getMetadataCollector()
.getLogicalColumnName( identifier.getTable(), identifier.getColumns().get(0).getQuotedName() );
return primaryKeyJoinColumn != null || joinColumn != null
? explicitJoinColumn( primaryKeyJoinColumn, joinColumn, joins, propertyHolder, context, defaultColumnName )
: implicitJoinColumn( joins, propertyHolder, context, defaultColumnName );
? explicitJoinColumn( primaryKeyJoinColumn, joinColumn, parent, context, defaultColumnName )
: implicitJoinColumn( parent, context, defaultColumnName );
}
private static AnnotatedJoinColumn explicitJoinColumn(
PrimaryKeyJoinColumn primaryKeyJoinColumn,
JoinColumn joinColumn,
Map<String, Join> joins,
PropertyHolder propertyHolder,
AnnotatedJoinColumns parent,
MetadataBuildingContext context,
String defaultColumnName) {
final String columnName;
@ -267,34 +252,35 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
final String columnDef = columnDefinition.isEmpty() ? null
: normalizer.toDatabaseIdentifierText( columnDefinition );
final String logicalColumnName = columnName != null && columnName.isEmpty()
? normalizer.normalizeIdentifierQuotingAsString(defaultColumnName)
? normalizer.normalizeIdentifierQuotingAsString( defaultColumnName )
: normalizer.normalizeIdentifierQuotingAsString( columnName );
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setSqlType( columnDef );
column.setLogicalColumnName( logicalColumnName );
column.setReferencedColumn( referencedColumnName );
// column.setPropertyHolder(propertyHolder);
column.setJoins(joins);
column.setBuildingContext(context);
// column.setJoins(joins);
// column.setContext( context );
column.setImplicit( false );
column.setNullable( false );
column.setParent( parent );
column.bind();
return column;
}
private static AnnotatedJoinColumn implicitJoinColumn(
Map<String, Join> joins,
PropertyHolder propertyHolder,
AnnotatedJoinColumns parent,
MetadataBuildingContext context,
String defaultColumnName ) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
column.setLogicalColumnName( normalizer.normalizeIdentifierQuotingAsString(defaultColumnName) );
column.setLogicalColumnName( normalizer.normalizeIdentifierQuotingAsString( defaultColumnName ) );
// column.setPropertyHolder( propertyHolder );
column.setJoins(joins);
column.setBuildingContext(context);
// column.setJoins(joins);
// column.setContext( context );
column.setImplicit( true );
column.setNullable( false );
column.setParent( parent );
column.bind();
return column;
}
@ -328,7 +314,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
SimpleValue value) {
final String logicalReferencedColumn = getBuildingContext().getMetadataCollector()
.getLogicalColumnName( referencedEntity.getTable(), referencedColumn.getQuotedName() );
final String columnName = parent.buildDefaultColumnName( referencedEntity, logicalReferencedColumn );
final String columnName = getParent().buildDefaultColumnName( referencedEntity, logicalReferencedColumn );
//yuk side effect on an implicit column
setLogicalColumnName( columnName );
setReferencedColumn( logicalReferencedColumn );
@ -347,7 +333,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
public void addDefaultJoinColumnName(PersistentClass referencedEntity, String logicalReferencedColumn) {
final String columnName = parent.buildDefaultColumnName( referencedEntity, logicalReferencedColumn );
final String columnName = getParent().buildDefaultColumnName( referencedEntity, logicalReferencedColumn );
getMappingColumn().setName( columnName );
setLogicalColumnName( columnName );
}
@ -373,7 +359,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
@Override
protected void addColumnBinding(SimpleValue value) {
if ( isEmpty( parent.getMappedBy() ) ) {
if ( isEmpty( getParent().getMappedBy() ) ) {
// was the column explicitly quoted in the mapping/annotation
// TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect to logical names
boolean isLogicalColumnQuoted = isQuoted( getLogicalColumnName() );
@ -407,12 +393,12 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
AnnotatedJoinColumns joinColumns,
PersistentClass referencedEntity,
MetadataBuildingContext context) {
final AnnotatedJoinColumn[] columns = joinColumns.getColumns();
if ( columns.length == 0 ) {
final List<AnnotatedJoinColumn> columns = joinColumns.getJoinColumns();
if ( columns.size() == 0 ) {
return NO_REFERENCE; //shortcut
}
final AnnotatedJoinColumn firstColumn = columns[0];
final AnnotatedJoinColumn firstColumn = columns.get(0);
final Object columnOwner = findReferencedColumnOwner( referencedEntity, firstColumn, context );
if ( columnOwner == null ) {
try {
@ -441,7 +427,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
if ( explicitColumnReference ) {
// if we got to here, all the columns belong to the PK
return keyColumns.size() == columns.length
return keyColumns.size() == columns.size()
// we have all the PK columns
? PK_REFERENCE
// we have a subset of the PK columns
@ -497,36 +483,36 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
static AnnotatedJoinColumn buildImplicitJoinTableJoinColumn(
Map<String, Join> secondaryTables,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext context) {
String propertyName) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setImplicit( true );
column.setNullable( false ); //I break the spec, but it's for good
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setJoins( secondaryTables );
column.setBuildingContext( context );
// column.setJoins( secondaryTables );
// column.setContext( context );
column.setParent( parent );
column.bind();
return column;
}
static AnnotatedJoinColumn buildExplicitJoinTableJoinColumn(
Map<String, Join> secondaryTables,
AnnotatedJoinColumns parent,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext context,
JoinColumn joinColumn) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setImplicit( true );
// column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setJoins( secondaryTables );
column.setBuildingContext( context );
column.setJoinAnnotation( joinColumn, propertyName );
// column.setJoins( secondaryTables );
// column.setContext( context );
column.setNullable( false ); //I break the spec, but it's for good
//done after the annotation to override it
column.setParent( parent );
column.applyJoinAnnotation( joinColumn, propertyName );
column.bind();
return column;
}
@ -548,8 +534,20 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
return string.toString();
}
@Override
public AnnotatedJoinColumns getParent() {
return (AnnotatedJoinColumns) super.getParent();
}
@Override
public void setParent(AnnotatedColumns parent) {
if ( !(parent instanceof AnnotatedJoinColumns) ) {
throw new UnsupportedOperationException("wrong kind of parent");
}
super.setParent( parent );
}
public void setParent(AnnotatedJoinColumns parent) {
super.setParent( parent );
this.parent = parent;
}
}

View File

@ -2,6 +2,7 @@ package org.hibernate.cfg;
import jakarta.persistence.JoinColumn;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinFormula;
@ -25,6 +26,8 @@ import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.SimpleValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -47,9 +50,8 @@ import static org.hibernate.internal.util.StringHelper.qualify;
*/
public class AnnotatedJoinColumns extends AnnotatedColumns {
private AnnotatedJoinColumn[] columns;
private final List<AnnotatedJoinColumn> columns = new ArrayList<>();
private String propertyName; // this is really a .-separated property path
private MetadataBuildingContext buildingContext;
//TODO: do we really need to hang so many strings off this class?
private String mappedBy;
@ -66,22 +68,23 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext context) {
final AnnotatedJoinColumn[] columns = new AnnotatedJoinColumn[joinColumnOrFormulas.length];
for ( int i = 0; i < joinColumnOrFormulas.length; i++ ) {
final JoinColumnOrFormula columnOrFormula = joinColumnOrFormulas[i];
final AnnotatedJoinColumns parent = new AnnotatedJoinColumns();
parent.setBuildingContext( context );
parent.setJoins( joins );
parent.setPropertyHolder( propertyHolder );
parent.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
parent.setMappedBy( mappedBy );
for ( JoinColumnOrFormula columnOrFormula : joinColumnOrFormulas ) {
final JoinFormula formula = columnOrFormula.formula();
final JoinColumn column = columnOrFormula.column();
columns[i] = formula.value() != null && !formula.value().isEmpty()
? AnnotatedJoinColumn.buildJoinFormula( formula, joins, propertyHolder, propertyName, context )
: AnnotatedJoinColumn.buildJoinColumn( column, mappedBy, joins, propertyHolder, propertyName, context );
if ( !isEmptyOrNullAnnotationValue( formula.value() ) ) {
AnnotatedJoinColumn.buildJoinFormula( formula, parent, propertyHolder, propertyName );
}
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
joinColumns.setColumns( columns );
joinColumns.setMappedBy( mappedBy );
return joinColumns;
else {
AnnotatedJoinColumn.buildJoinColumn( column, mappedBy, parent, propertyHolder, propertyName );
}
}
return parent;
}
public static AnnotatedJoinColumns buildJoinColumns(
@ -116,47 +119,38 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
final String path = qualify( propertyHolder.getPath(), propertyName );
final JoinColumn[] overriddes = propertyHolder.getOverriddenJoinColumn( path );
final JoinColumn[] actualColumns = overriddes == null ? joinColumns : overriddes;
final AnnotatedJoinColumns parent = new AnnotatedJoinColumns();
parent.setBuildingContext( context );
parent.setJoins( joins );
parent.setPropertyHolder( propertyHolder );
parent.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
parent.setMappedBy( mappedBy );
if ( actualColumns == null || actualColumns.length == 0 ) {
final AnnotatedJoinColumn joinColumn = AnnotatedJoinColumn.buildJoinColumn(
AnnotatedJoinColumn.buildJoinColumn(
null,
comment,
mappedBy,
joins,
parent,
propertyHolder,
propertyName,
defaultColumnSuffix,
context
defaultColumnSuffix
);
final AnnotatedJoinColumns annotatedJoinColumns = new AnnotatedJoinColumns();
annotatedJoinColumns.setBuildingContext( context );
annotatedJoinColumns.setPropertyHolder( propertyHolder );
annotatedJoinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
annotatedJoinColumns.setColumns( new AnnotatedJoinColumn[] { joinColumn } );
annotatedJoinColumns.setMappedBy( mappedBy );
return annotatedJoinColumns;
}
else {
final AnnotatedJoinColumn[] result = new AnnotatedJoinColumn[actualColumns.length];
for ( int index = 0; index < actualColumns.length; index++ ) {
result[index] = AnnotatedJoinColumn.buildJoinColumn(
actualColumns[index],
parent.setMappedBy( mappedBy );
for ( JoinColumn actualColumn : actualColumns ) {
AnnotatedJoinColumn.buildJoinColumn(
actualColumn,
comment,
mappedBy,
joins,
parent,
propertyHolder,
propertyName,
defaultColumnSuffix,
context
defaultColumnSuffix
);
}
final AnnotatedJoinColumns annotatedJoinColumns = new AnnotatedJoinColumns();
annotatedJoinColumns.setBuildingContext( context );
annotatedJoinColumns.setPropertyHolder( propertyHolder );
annotatedJoinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
annotatedJoinColumns.setColumns( result );
annotatedJoinColumns.setMappedBy( mappedBy );
return annotatedJoinColumns;
}
return parent;
}
public static AnnotatedJoinColumns buildJoinTableJoinColumns(
@ -166,56 +160,39 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
String propertyName,
String mappedBy,
MetadataBuildingContext context) {
final AnnotatedJoinColumn[] columns;
final AnnotatedJoinColumns parent = new AnnotatedJoinColumns();
parent.setBuildingContext( context );
parent.setJoins( secondaryTables );
parent.setPropertyHolder( propertyHolder );
parent.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
parent.setMappedBy( mappedBy );
if ( joinColumns == null ) {
columns = new AnnotatedJoinColumn[] { AnnotatedJoinColumn.buildImplicitJoinTableJoinColumn(
secondaryTables,
propertyHolder,
propertyName,
context
) };
AnnotatedJoinColumn.buildImplicitJoinTableJoinColumn( parent, propertyHolder, propertyName );
}
else {
columns = new AnnotatedJoinColumn[joinColumns.length];
int length = joinColumns.length;
for (int index = 0; index < length; index++) {
columns[index] = AnnotatedJoinColumn.buildExplicitJoinTableJoinColumn(
secondaryTables,
propertyHolder,
propertyName,
context,
joinColumns[index]
);
for ( JoinColumn joinColumn : joinColumns ) {
AnnotatedJoinColumn.buildExplicitJoinTableJoinColumn( parent, propertyHolder, propertyName, joinColumn );
}
}
final AnnotatedJoinColumns annotatedJoinColumns = new AnnotatedJoinColumns();
annotatedJoinColumns.setBuildingContext( context );
annotatedJoinColumns.setPropertyHolder( propertyHolder );
annotatedJoinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
annotatedJoinColumns.setColumns( columns );
annotatedJoinColumns.setMappedBy( mappedBy );
return annotatedJoinColumns;
return parent;
}
public AnnotatedJoinColumn[] getColumns() {
public List<AnnotatedJoinColumn> getJoinColumns() {
return columns;
}
@Override
public void setColumns(AnnotatedColumn[] columns) {
throw new UnsupportedOperationException( "wrong sort of columns" );
public void addColumn(AnnotatedColumn child) {
if ( !(child instanceof AnnotatedJoinColumn) ) {
throw new AssertionFailure( "wrong sort of column" );
}
addColumn( (AnnotatedJoinColumn) child );
}
public void setColumns(AnnotatedJoinColumn[] columns) {
super.setColumns( columns );
this.columns = columns;
if ( columns != null ) {
for ( AnnotatedJoinColumn column : columns ) {
column.setParent( this );
public void addColumn(AnnotatedJoinColumn child) {
super.addColumn( child );
columns.add( child );
}
}
}
public String getMappedBy() {
return mappedBy;
}
@ -258,7 +235,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
final PropertyHolder propertyHolder = buildPropertyHolder(
persistentClass,
joins,
buildingContext,
getBuildingContext(),
inheritanceStatePerClass
);
setPropertyHolder( propertyHolder );
@ -267,10 +244,6 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
// }
}
public void setBuildingContext(MetadataBuildingContext buildingContext) {
this.buildingContext = buildingContext;
}
public boolean isElementCollection() {
return elementCollection;
}
@ -294,7 +267,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
}
String buildDefaultColumnName(PersistentClass referencedEntity, String logicalReferencedColumn) {
final MetadataBuildingOptions options = buildingContext.getBuildingOptions();
final MetadataBuildingOptions options = getBuildingContext().getBuildingOptions();
final ImplicitNamingStrategy implicitNamingStrategy = options.getImplicitNamingStrategy();
final PhysicalNamingStrategy physicalNamingStrategy = options.getPhysicalNamingStrategy();
@ -302,7 +275,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
boolean ownerSide = getPropertyName() != null;
boolean isRefColumnQuoted = isQuoted( logicalReferencedColumn );
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
final Database database = collector.getDatabase();
Identifier columnIdentifier;
@ -350,7 +323,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
new ImplicitPrimaryKeyJoinColumnNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
return AnnotatedJoinColumns.this.getBuildingContext();
}
@Override
@ -407,7 +380,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
private final Identifier referencedTableName;
private final String logicalReferencedColumn;
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
final Database database = collector.getDatabase();
public UnownedImplicitJoinColumnNameSource(PersistentClass referencedEntity, String logicalReferencedColumn) {
@ -505,7 +478,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
return AnnotatedJoinColumns.this.getBuildingContext();
}
}
@ -518,7 +491,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
private final Identifier referencedTableName;
private final Identifier referencedColumnName;
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
final Database database = collector.getDatabase();
public OwnedImplicitJoinColumnNameSource(PersistentClass referencedEntity, String logicalTableName, String logicalReferencedColumn) {
@ -571,7 +544,7 @@ public class AnnotatedJoinColumns extends AnnotatedColumns {
@Override
public MetadataBuildingContext getBuildingContext() {
return buildingContext;
return AnnotatedJoinColumns.this.getBuildingContext();
}
}
}

View File

@ -1510,16 +1510,23 @@ public final class AnnotationBinder {
if ( isOverridden ) {
// careful: not always a @MapsId property, sometimes it's from an @IdClass
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
propertyBinder.isId(), propertyHolder, property.getName(), context
propertyBinder.isId(),
propertyHolder,
property.getName(),
context
);
referencedEntityName = mapsIdProperty.getClassOrElementName();
propertyName = mapsIdProperty.getPropertyName();
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns.getColumns() );
actualColumns = joinColumns;
final AnnotatedJoinColumns parent = new AnnotatedJoinColumns();
parent.setBuildingContext( context );
parent.setPropertyHolder( propertyHolder );
parent.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
//TODO: resetting the parent here looks like a dangerous thing to do
// should we be cloning them first (the legacy code did not)
for ( AnnotatedColumn column : columns.getColumns() ) {
column.setParent( parent );
}
actualColumns = parent;
}
else {
referencedEntityName = null;
@ -1579,7 +1586,7 @@ public final class AnnotationBinder {
final JoinTable assocTable = propertyHolder.getJoinTable(property);
if ( assocTable != null ) {
Join join = propertyHolder.addJoin( assocTable, false );
for ( AnnotatedJoinColumn joinColumn : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn joinColumn : joinColumns.getJoinColumns() ) {
joinColumn.setExplicitTableName( join.getTable().getName() );
}
}
@ -2247,7 +2254,7 @@ public final class AnnotationBinder {
binder.setUpdatable( false );
}
else {
final AnnotatedJoinColumn firstColumn = columns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = columns.getJoinColumns().get(0);
binder.setInsertable( firstColumn.isInsertable() );
binder.setUpdatable( firstColumn.isUpdatable() );
}

View File

@ -172,18 +172,16 @@ public class BinderHelper {
// true when we do the reverse side of a @ManyToMany
boolean inverse,
MetadataBuildingContext context) {
final AnnotatedJoinColumn[] columns = joinColumns.getColumns();
// this work is not necessary for a primary key reference
if ( checkReferencedColumnsType( joinColumns, targetEntity, context ) == NON_PK_REFERENCE ) { // && !firstColumn.isImplicit()
// all the columns have to belong to the same table;
// figure out which table has the columns by looking
// for a PersistentClass or Join in the hierarchy of
// the target entity which has the first column
final Object columnOwner = findReferencedColumnOwner( targetEntity, columns[0], context );
final Object columnOwner = findReferencedColumnOwner( targetEntity, joinColumns.getJoinColumns().get(0), context );
checkColumnInSameTable( joinColumns, targetEntity, associatedEntity, context, columnOwner );
// find all properties mapped to each column
final List<Property> properties = findPropertiesByColumns( columnOwner, columns, associatedEntity, context );
final List<Property> properties = findPropertiesByColumns( columnOwner, joinColumns, associatedEntity, context );
// create a Property along with the new synthetic
// Component if necessary (or reuse the existing
// Property that matches exactly)
@ -224,19 +222,19 @@ public class BinderHelper {
// we should only get called for owning side of association
throw new AssertionFailure("no need to create synthetic properties for unowned collections");
}
for ( AnnotatedJoinColumn column: joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn column: joinColumns.getJoinColumns() ) {
final Object owner = findReferencedColumnOwner( targetEntity, column, context );
if ( owner == null ) {
throw new AnnotationException( "A '@JoinColumn' for association "
+ associationMessage( associatedEntity, column )
+ associationMessage( associatedEntity, joinColumns )
+ " references a column named '" + column.getReferencedColumn()
+ "' which is not mapped by the target entity '"
+ targetEntity.getEntityName() + "'" );
}
if ( owner != columnOwner) {
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
throw new AnnotationException( "The '@JoinColumn's for association "
+ associationMessage( associatedEntity, column )
+ associationMessage( associatedEntity, joinColumns )
+ " reference columns of different tables mapped by the target entity '"
+ targetEntity.getEntityName() + "' ('" + column.getReferencedColumn() +
"' belongs to a different table to '" + firstColumn.getReferencedColumn() + "'" );
@ -334,21 +332,21 @@ public class BinderHelper {
return syntheticPropertyName;
}
private static String associationMessage(PersistentClass associatedEntity, AnnotatedJoinColumn firstColumn) {
private static String associationMessage(PersistentClass associatedEntity, AnnotatedJoinColumns joinColumns) {
StringBuilder message = new StringBuilder();
if ( associatedEntity != null ) {
message.append( "'" )
.append( associatedEntity.getEntityName() )
.append( "." )
.append( firstColumn.getPropertyName() )
.append( joinColumns.getPropertyName() )
.append( "'" );
}
else {
if ( firstColumn.getPropertyHolder() != null ) {
if ( joinColumns.getPropertyHolder() != null ) {
message.append( "'" )
.append( firstColumn.getPropertyHolder().getEntityName() )
.append( joinColumns.getPropertyHolder().getEntityName() )
.append( "." )
.append( firstColumn.getPropertyName() )
.append( joinColumns.getPropertyName() )
.append( "'" );
}
}
@ -415,7 +413,7 @@ public class BinderHelper {
private static List<Property> findPropertiesByColumns(
Object columnOwner,
AnnotatedJoinColumn[] columns,
AnnotatedJoinColumns columns,
PersistentClass associatedEntity,
MetadataBuildingContext context) {
@ -436,12 +434,12 @@ public class BinderHelper {
// Build the list of column names in the exact order they were
// specified by the @JoinColumn annotations.
final List<Column> orderedColumns = new ArrayList<>( columns.length );
final List<Column> orderedColumns = new ArrayList<>( columns.getJoinColumns().size() );
final Map<Column, Set<Property>> columnsToProperty = new HashMap<>();
final InFlightMetadataCollector collector = context.getMetadataCollector();
for ( AnnotatedJoinColumn joinColumn : columns ) {
for ( AnnotatedJoinColumn joinColumn : columns.getJoinColumns() ) {
if ( joinColumn.isReferenceImplicit() ) {
throw new AnnotationException("Association " + associationMessage( associatedEntity, joinColumn )
throw new AnnotationException("Association " + associationMessage( associatedEntity, columns )
+ " has a '@JoinColumn' which does not specify the 'referencedColumnName'"
+ " (when an association has multiple '@JoinColumn's, they must each specify their 'referencedColumnName')");
}
@ -492,7 +490,7 @@ public class BinderHelper {
if ( properties.isEmpty() ) {
// no property found which maps to this column
throw new AnnotationException( "Referenced column '" + column.getName()
+ "' in '@JoinColumn' for " + associationMessage( associatedEntity, columns[0] )
+ "' in '@JoinColumn' for " + associationMessage( associatedEntity, columns )
+ " is not mapped by any property of the target entity" );
}
for ( Property property : properties ) {
@ -503,7 +501,7 @@ public class BinderHelper {
throw new AnnotationException( "Referenced column '" + column.getName()
+ "' mapped by target property '" + property.getName()
+ "' occurs out of order in the list of '@JoinColumn's for association "
+ associationMessage( associatedEntity, columns[0] ) );
+ associationMessage( associatedEntity, columns ) );
}
lastPropertyColumnIndex++;
if ( lastPropertyColumnIndex == currentProperty.getColumnSpan() ) {
@ -516,7 +514,7 @@ public class BinderHelper {
// we didn't use up all the columns of the previous property
throw new AnnotationException( "Target property '" + property.getName() + "' has "
+ property.getColumnSpan() + " columns which must be referenced by a '@JoinColumn' for "
+ associationMessage( associatedEntity, columns[0] )
+ associationMessage( associatedEntity, columns )
+ " (every column mapped by '" + property.getName()
+ "' must occur exactly once as a 'referencedColumnName', and in the correct order)" );
}
@ -524,7 +522,7 @@ public class BinderHelper {
// we already used up all the columns of this property
throw new AnnotationException( "Target property '" + property.getName() + "' has only "
+ property.getColumnSpan() + " columns which may be referenced by a '@JoinColumn' for "
+ associationMessage( associatedEntity, columns[0] )
+ associationMessage( associatedEntity, columns )
+ " (each column mapped by '" + property.getName()
+ "' may only occur once as a 'referencedColumnName')" );
@ -1070,7 +1068,7 @@ public class BinderHelper {
entityBinder.getSecondaryTables(),
context
);
assert discriminatorColumns.getColumns().length == 1;
assert discriminatorColumns.getColumns().size() == 1;
discriminatorColumns.setTable( value.getTable() );
discriminatorValueBinder.setColumns( discriminatorColumns );
@ -1082,7 +1080,7 @@ public class BinderHelper {
value.setDiscriminator( discriminatorDescriptor );
discriminatorValueBinder.fillSimpleValue();
// TODO: this is nasty
final AnnotatedColumn firstDiscriminatorColumn = discriminatorColumns.getColumns()[0];
final AnnotatedColumn firstDiscriminatorColumn = discriminatorColumns.getColumns().get(0);
firstDiscriminatorColumn.linkWithValue( discriminatorDescriptor );
final JavaType<?> discriminatorJavaType = discriminatorDescriptor
@ -1100,8 +1098,8 @@ public class BinderHelper {
value.setDiscriminatorValueMappings( discriminatorValueMappings );
final BasicValueBinder keyValueBinder = new BasicValueBinder( BasicValueBinder.Kind.ANY_KEY, context );
final AnnotatedJoinColumn[] columns = keyColumns.getColumns();
assert columns.length == 1;
final List<AnnotatedJoinColumn> columns = keyColumns.getJoinColumns();
assert columns.size() == 1;
keyColumns.setTable( value.getTable() );
keyValueBinder.setColumns( keyColumns );
if ( !optional ) {
@ -1114,8 +1112,8 @@ public class BinderHelper {
value.setKey( keyDescriptor );
keyValueBinder.fillSimpleValue();
final String path = qualify( propertyHolder.getEntityName(), inferredData.getPropertyName() );
AnnotatedColumn.checkPropertyConsistency( columns, path );
columns[0].linkWithValue( keyDescriptor );
AnnotatedColumn.checkPropertyConsistency( keyColumns.getColumns(), path );
columns.get(0).linkWithValue( keyDescriptor ); //TODO: nasty
return value;
}
@ -1175,23 +1173,22 @@ public class BinderHelper {
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
final XClass persistentXClass = buildingContext.getBootstrapContext().getReflectionManager()
final XClass mappedClass = buildingContext.getBootstrapContext().getReflectionManager()
.toXClass( propertyHolder.getPersistentClass().getMappedClass() );
final InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
if ( propertyHolder.isInIdClass() ) {
PropertyData pd = metadataCollector.getPropertyAnnotatedWithIdAndToOne( persistentXClass, propertyName );
if ( pd == null && buildingContext.getBuildingOptions().isSpecjProprietarySyntaxEnabled() ) {
pd = metadataCollector.getPropertyAnnotatedWithMapsId( persistentXClass, propertyName );
}
return pd;
final PropertyData propertyData = metadataCollector.getPropertyAnnotatedWithIdAndToOne( mappedClass, propertyName );
return propertyData == null && buildingContext.getBuildingOptions().isSpecjProprietarySyntaxEnabled()
? metadataCollector.getPropertyAnnotatedWithMapsId( mappedClass, propertyName )
: propertyData;
}
else {
return metadataCollector.getPropertyAnnotatedWithMapsId( persistentXClass, isId ? "" : propertyName);
return metadataCollector.getPropertyAnnotatedWithMapsId( mappedClass, isId ? "" : propertyName );
}
}
public static Map<String,String> toAliasTableMap(SqlFragmentAlias[] aliases){
Map<String,String> ret = new HashMap<>();
final Map<String,String> ret = new HashMap<>();
for ( SqlFragmentAlias aliase : aliases ) {
if ( isNotEmpty( aliase.table() ) ) {
ret.put( aliase.alias(), aliase.table() );
@ -1201,13 +1198,13 @@ public class BinderHelper {
}
public static Map<String,String> toAliasEntityMap(SqlFragmentAlias[] aliases){
Map<String,String> ret = new HashMap<>();
final Map<String,String> result = new HashMap<>();
for ( SqlFragmentAlias aliase : aliases ) {
if ( aliase.entity() != void.class ) {
ret.put( aliase.alias(), aliase.entity().getName() );
result.put( aliase.alias(), aliase.entity().getName() );
}
}
return ret;
return result;
}
public static boolean hasToOneAnnotation(XAnnotatedElement property) {
@ -1219,13 +1216,13 @@ public class BinderHelper {
XAnnotatedElement element,
Class<T> annotationType,
MetadataBuildingContext context) {
Dialect dialect = context.getMetadataCollector().getDatabase().getDialect();
Iterator<Annotation> annotations =
final Dialect dialect = context.getMetadataCollector().getDatabase().getDialect();
final Iterator<Annotation> annotations =
Arrays.stream( element.getAnnotations() )
.flatMap(annotation -> {
.flatMap( annotation -> {
try {
Method value = annotation.annotationType().getDeclaredMethod("value");
Class<?> returnType = value.getReturnType();
final Method value = annotation.annotationType().getDeclaredMethod("value");
final Class<?> returnType = value.getReturnType();
if ( returnType.isArray()
&& returnType.getComponentType().isAnnotationPresent(Repeatable.class)
&& returnType.getComponentType().isAnnotationPresent(DialectOverride.OverridesAnnotation.class) ) {
@ -1237,21 +1234,22 @@ public class BinderHelper {
throw new AssertionFailure("could not read @DialectOverride annotation", e);
}
return Stream.of(annotation);
}).iterator();
} ).iterator();
while ( annotations.hasNext() ) {
Annotation annotation = annotations.next();
Class<? extends Annotation> type = annotation.annotationType();
DialectOverride.OverridesAnnotation overridesAnnotation = type.getAnnotation(DialectOverride.OverridesAnnotation.class);
final Annotation annotation = annotations.next();
final Class<? extends Annotation> type = annotation.annotationType();
final DialectOverride.OverridesAnnotation overridesAnnotation =
type.getAnnotation(DialectOverride.OverridesAnnotation.class);
if ( overridesAnnotation != null
&& overridesAnnotation.value().equals(annotationType) ) {
try {
//noinspection unchecked
Class<? extends Dialect> overrideDialect = (Class<? extends Dialect>)
final Class<? extends Dialect> overrideDialect = (Class<? extends Dialect>)
type.getDeclaredMethod("dialect").invoke(annotation);
if ( overrideDialect.isAssignableFrom( dialect.getClass() ) ) {
DialectOverride.Version before = (DialectOverride.Version)
final DialectOverride.Version before = (DialectOverride.Version)
type.getDeclaredMethod("before").invoke(annotation);
DialectOverride.Version sameOrAfter = (DialectOverride.Version)
final DialectOverride.Version sameOrAfter = (DialectOverride.Version)
type.getDeclaredMethod("sameOrAfter").invoke(annotation);
if ( dialect.getVersion().isBefore( before.major(), before.minor() )
&& dialect.getVersion().isSameOrAfter( sameOrAfter.major(), sameOrAfter.minor() ) ) {
@ -1306,8 +1304,8 @@ public class BinderHelper {
Cascade hibernateCascadeAnnotation,
boolean orphanRemoval,
boolean forcePersist) {
EnumSet<CascadeType> cascadeTypes = convertToHibernateCascadeType( ejbCascades );
CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ? null : hibernateCascadeAnnotation.value();
final EnumSet<CascadeType> cascadeTypes = convertToHibernateCascadeType( ejbCascades );
final CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ? null : hibernateCascadeAnnotation.value();
if ( hibernateCascades != null && hibernateCascades.length > 0 ) {
cascadeTypes.addAll( Arrays.asList( hibernateCascades ) );
}
@ -1322,7 +1320,7 @@ public class BinderHelper {
}
private static String renderCascadeTypeList(EnumSet<CascadeType> cascadeTypes) {
StringBuilder cascade = new StringBuilder();
final StringBuilder cascade = new StringBuilder();
for ( CascadeType cascadeType : cascadeTypes) {
switch ( cascadeType ) {
case ALL:

View File

@ -12,7 +12,6 @@ import jakarta.persistence.Convert;
import jakarta.persistence.Converts;
import jakarta.persistence.JoinTable;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.annotations.common.reflection.XClass;
@ -183,18 +182,10 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
}
public void addProperty(Property prop, AnnotatedColumns columns, XClass declaringClass) {
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
//AnnotatedColumn.checkPropertyConsistency( ); //already called earlier
if ( columns != null ) {
final AnnotatedColumn firstColumn = columns.getColumns()[0];
if ( firstColumn.isSecondary() ) {
//TODO move the getJoin() code here?
for ( AnnotatedColumn column : columns.getColumns() ) {
if ( !column.isSecondary() || column.getJoin() != firstColumn.getJoin() ) {
//TODO: fix the error message
throw new AnnotationException("different columns mapped to different tables for a single property");
}
}
addPropertyToJoin( prop, declaringClass, firstColumn.getJoin() );
if ( columns.isSecondary() ) {
addPropertyToJoin( prop, declaringClass, columns.getJoin() );
}
else {
addProperty( prop, declaringClass );

View File

@ -239,19 +239,12 @@ class ColumnsBuilder {
}
private AnnotatedJoinColumns buildJoinColumnsWithFormula(String propertyName, JoinFormula joinFormula) {
final AnnotatedJoinColumn[] columns = new AnnotatedJoinColumn[1];
columns[0] = AnnotatedJoinColumn.buildJoinFormula(
joinFormula,
entityBinder.getSecondaryTables(),
propertyHolder,
propertyName,
buildingContext
);
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( buildingContext );
joinColumns.setJoins( entityBinder.getSecondaryTables() );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName) );
joinColumns.setColumns( columns );
joinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
AnnotatedJoinColumn.buildJoinFormula( joinFormula, joinColumns, propertyHolder, propertyName );
return joinColumns;
}
@ -260,13 +253,13 @@ class ColumnsBuilder {
return new JoinColumnOrFormula[] { property.getAnnotation( JoinColumnOrFormula.class ) };
}
else if ( property.isAnnotationPresent( JoinColumnsOrFormulas.class ) ) {
JoinColumnsOrFormulas joinColumnsOrFormulasAnnotations = property.getAnnotation( JoinColumnsOrFormulas.class );
final JoinColumnOrFormula[] joinColumnOrFormulaAnnotations = joinColumnsOrFormulasAnnotations.value();
if ( joinColumnOrFormulaAnnotations.length == 0 ) {
final JoinColumnsOrFormulas joinColumnsOrFormulas = property.getAnnotation( JoinColumnsOrFormulas.class );
final JoinColumnOrFormula[] joinColumnOrFormula = joinColumnsOrFormulas.value();
if ( joinColumnOrFormula.length == 0 ) {
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData)
+ "' has an empty '@JoinColumnsOrFormulas' annotation" );
}
return joinColumnOrFormulaAnnotations;
return joinColumnOrFormula;
}
else {
return null;
@ -278,33 +271,34 @@ class ColumnsBuilder {
return new JoinColumn[] { property.getAnnotation( JoinColumn.class ) };
}
else if ( property.isAnnotationPresent( JoinColumns.class ) ) {
final JoinColumns joinColumnAnnotation = property.getAnnotation( JoinColumns.class );
final JoinColumn[] joinColumnAnnotations = joinColumnAnnotation.value();
if ( joinColumnAnnotations.length == 0 ) {
final JoinColumns joinColumns = property.getAnnotation( JoinColumns.class );
final JoinColumn[] joinColumn = joinColumns.value();
if ( joinColumn.length == 0 ) {
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData)
+ "' has an empty '@JoinColumns' annotation" );
}
return joinColumnAnnotations;
return joinColumn;
}
else {
return null;
}
}
AnnotatedColumns overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
final PropertyData overridingProperty =
getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder, property.getName(), buildingContext );
return overridingProperty != null ? buildExplicitOrDefaultJoinColumn( overridingProperty ) : columns;
}
/**
* Useful to override a column either by {@code @MapsId} or by {@code @IdClass}
*/
//TODO: should we introduce an AnnotatedColumns type and return that here?
private AnnotatedColumns buildExplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
final AnnotatedJoinColumns columns = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
return columns == null
? buildDefaultJoinColumnsForToOne( overridingProperty.getProperty(), overridingProperty )
: columns;
AnnotatedColumns overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
final PropertyData override =
getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder, property.getName(), buildingContext );
if ( override != null ) {
final AnnotatedJoinColumns joinColumns = buildExplicitJoinColumns( override.getProperty(), override );
return joinColumns == null
? buildDefaultJoinColumnsForToOne( override.getProperty(), override )
: joinColumns;
}
else {
return columns;
}
}
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.cfg;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -67,12 +68,12 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
@Override
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
PersistentClass referencedPersistentClass = persistentClasses.get( referencedEntityName );
final PersistentClass referencedPersistentClass = persistentClasses.get( referencedEntityName );
if ( referencedPersistentClass == null ) {
// TODO: much better error message if this is something that can really happen!
throw new AnnotationException( "Unknown entity name '" + referencedEntityName + "'");
}
KeyValue identifier = referencedPersistentClass.getIdentifier();
final KeyValue identifier = referencedPersistentClass.getIdentifier();
if ( !(identifier instanceof Component) ) {
// The entity with the @MapsId annotation has a composite
// id type, but the referenced entity has a basic-typed id.
@ -87,13 +88,13 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
);
}
Component referencedComponent = (Component) identifier;
final Component referencedComponent = (Component) identifier;
//prepare column name structure
boolean isExplicitReference = true;
final AnnotatedJoinColumn[] cols = joinColumns.getColumns();
final Map<String, AnnotatedJoinColumn> columnByReferencedName = mapOfSize( cols.length );
for ( AnnotatedJoinColumn joinColumn : cols) {
final List<AnnotatedJoinColumn> columns = joinColumns.getJoinColumns();
final Map<String, AnnotatedJoinColumn> columnByReferencedName = mapOfSize( columns.size() );
for ( AnnotatedJoinColumn joinColumn : columns ) {
if ( !joinColumn.isReferenceImplicit() ) {
//JPA 2 requires referencedColumnNames to be case-insensitive
columnByReferencedName.put( joinColumn.getReferencedColumn().toLowerCase(Locale.ROOT), joinColumn );
@ -102,8 +103,8 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
//try default column orientation
if ( columnByReferencedName.isEmpty() ) {
isExplicitReference = false;
for (int i = 0; i < cols.length; i++ ) {
columnByReferencedName.put( String.valueOf( i ), cols[i] );
for (int i = 0; i < columns.size(); i++ ) {
columnByReferencedName.put( String.valueOf( i ), columns.get(i) );
}
}
@ -185,7 +186,8 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
final SimpleValue referencedValue = (SimpleValue) referencedProperty.getValue();
value.copyTypeFrom( referencedValue );
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
//TODO: this bit is nasty, move up to AnnotatedJoinColumns
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
if ( firstColumn.isNameDeferred() ) {
firstColumn.copyReferencedStructureAndCreateDefaultJoinColumns(
referencedPersistentClass,

View File

@ -29,53 +29,48 @@ public class IndexColumn extends AnnotatedColumn {
}
public static IndexColumn fromAnnotations(
OrderColumn jpaAnnotation,
org.hibernate.annotations.IndexColumn hibAnnotation,
ListIndexBase indexBaseAnnotation,
OrderColumn orderColumn,
org.hibernate.annotations.IndexColumn indexColumn,
ListIndexBase listIndexBase,
PropertyHolder propertyHolder,
PropertyData inferredData,
Map<String, Join> secondaryTables,
MetadataBuildingContext context) {
final IndexColumn column;
if ( jpaAnnotation != null ) {
column = buildColumnFromAnnotation(
jpaAnnotation,
propertyHolder,
inferredData,
secondaryTables,
context
);
if ( orderColumn != null ) {
column = buildColumnFromAnnotation( orderColumn, propertyHolder, inferredData, secondaryTables, context );
}
else if ( hibAnnotation != null ) {
column = buildColumnFromAnnotation(
hibAnnotation,
propertyHolder,
inferredData,
context
);
column.setBase( hibAnnotation.base() );
else if ( indexColumn != null ) {
column = buildColumnFromAnnotation( indexColumn, propertyHolder, inferredData, context );
column.setBase( indexColumn.base() );
}
else {
column = new IndexColumn();
column.setLogicalColumnName( inferredData.getPropertyName() + "_ORDER" ); //JPA default name
column.setImplicit( true );
column.setBuildingContext( context );
// column.setContext( context );
// column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, column );
createParent( propertyHolder, secondaryTables, column, context );
column.bind();
}
if ( indexBaseAnnotation != null ) {
column.setBase( indexBaseAnnotation.value() );
if ( listIndexBase != null ) {
column.setBase( listIndexBase.value() );
}
return column;
}
private static void createParent(PropertyHolder propertyHolder, IndexColumn column) {
final AnnotatedColumns columns = new AnnotatedColumns();
columns.setColumns( new AnnotatedColumn[] {column} );
columns.setPropertyHolder( propertyHolder );
private static void createParent(
PropertyHolder propertyHolder,
Map<String,Join> secondaryTables,
IndexColumn column,
MetadataBuildingContext context) {
final AnnotatedColumns parent = new AnnotatedColumns();
parent.setPropertyHolder( propertyHolder );
parent.setJoins( secondaryTables );
parent.setBuildingContext( context );
column.setParent( parent );
}
public int getBase() {
@ -101,30 +96,29 @@ public class IndexColumn extends AnnotatedColumn {
PropertyHolder propertyHolder,
PropertyData inferredData,
Map<String, Join> secondaryTables,
MetadataBuildingContext buildingContext) {
MetadataBuildingContext context) {
if ( orderColumn != null ) {
final String sqlType = isEmptyAnnotationValue( orderColumn.columnDefinition() ) ? null : orderColumn.columnDefinition();
final String name = isEmptyAnnotationValue( orderColumn.name() ) ? inferredData.getPropertyName() + "_ORDER" : orderColumn.name();
//TODO move it to a getter based system and remove the constructor
final IndexColumn column = new IndexColumn();
column.setLogicalColumnName( name );
column.setSqlType( sqlType );
column.setNullable( orderColumn.nullable() );
column.setJoins( secondaryTables );
// column.setJoins( secondaryTables );
column.setInsertable( orderColumn.insertable() );
column.setUpdatable( orderColumn.updatable() );
column.setBuildingContext( buildingContext );
// column.setContext( context );
// column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, column );
createParent( propertyHolder, secondaryTables, column, context );
column.bind();
return column;
}
else {
final IndexColumn column = new IndexColumn();
column.setImplicit( true );
column.setBuildingContext( buildingContext );
// column.setContext( context );
// column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, column );
createParent( propertyHolder, secondaryTables, column, context );
column.bind();
return column;
}
@ -133,38 +127,38 @@ public class IndexColumn extends AnnotatedColumn {
/**
* Legacy {@link IndexColumn @IndexColumn} processing.
*
* @param ann The IndexColumn annotation instance
* @param indexColumn The IndexColumn annotation instance
* @param propertyHolder Information about the property
* @param inferredData Yeah, right. Uh...
*
* @return The index column
*/
public static IndexColumn buildColumnFromAnnotation(
org.hibernate.annotations.IndexColumn ann,
org.hibernate.annotations.IndexColumn indexColumn,
PropertyHolder propertyHolder,
PropertyData inferredData,
MetadataBuildingContext buildingContext) {
if ( ann != null ) {
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name();
MetadataBuildingContext context) {
if ( indexColumn != null ) {
final String sqlType = isEmptyAnnotationValue( indexColumn.columnDefinition() ) ? null : indexColumn.columnDefinition();
final String name = isEmptyAnnotationValue( indexColumn.name() ) ? inferredData.getPropertyName() : indexColumn.name();
//TODO move it to a getter based system and remove the constructor
final IndexColumn column = new IndexColumn();
column.setLogicalColumnName( name );
column.setSqlType( sqlType );
column.setNullable( ann.nullable() );
column.setBase( ann.base() );
column.setBuildingContext( buildingContext );
column.setNullable( indexColumn.nullable() );
column.setBase( indexColumn.base() );
// column.setContext( context );
// column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, column );
createParent( propertyHolder, null, column, context );
column.bind();
return column;
}
else {
final IndexColumn column = new IndexColumn();
column.setImplicit( true );
column.setBuildingContext( buildingContext );
// column.setContext( context );
// column.setPropertyHolder( propertyHolder );
createParent( propertyHolder, column );
createParent( propertyHolder, null, column, context );
column.bind();
return column;
}

View File

@ -91,7 +91,7 @@ public class ToOneBinder {
final JoinTable joinTable = propertyHolder.getJoinTable( property );
if ( joinTable != null ) {
final Join join = propertyHolder.addJoin( joinTable, false );
for ( AnnotatedJoinColumn joinColumn : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn joinColumn : joinColumns.getJoinColumns() ) {
joinColumn.setExplicitTableName( join.getTable().getName() );
}
}
@ -155,14 +155,14 @@ public class ToOneBinder {
value.setCascadeDeleteEnabled( cascadeOnDelete );
//value.setLazy( fetchMode != FetchMode.JOIN );
if ( !optional ) {
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn column : joinColumns.getJoinColumns() ) {
column.setNullable( false );
}
}
if ( property.isAnnotationPresent( MapsId.class ) ) {
//read only
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn column : joinColumns.getJoinColumns() ) {
column.setInsertable( false );
column.setUpdatable( false );
}
@ -228,7 +228,7 @@ public class ToOneBinder {
&& joinColumn.name().equals( columnName )
&& !property.isAnnotationPresent( MapsId.class ) ) {
hasSpecjManyToOne = true;
for ( AnnotatedJoinColumn column : columns.getColumns() ) {
for ( AnnotatedJoinColumn column : columns.getJoinColumns() ) {
column.setInsertable( false );
column.setUpdatable( false );
}
@ -256,16 +256,16 @@ public class ToOneBinder {
propertyBinder.setName( propertyName );
propertyBinder.setValue( value );
//binder.setCascade(cascadeStrategy);
if (isIdentifierMapper) {
if ( isIdentifierMapper ) {
propertyBinder.setInsertable( false );
propertyBinder.setUpdatable( false );
}
else if (hasSpecjManyToOne) {
else if ( hasSpecjManyToOne ) {
propertyBinder.setInsertable( false );
propertyBinder.setUpdatable( false );
}
else {
final AnnotatedJoinColumn firstColumn = columns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = columns.getJoinColumns().get(0);
propertyBinder.setInsertable( firstColumn.isInsertable() );
propertyBinder.setUpdatable( firstColumn.isUpdatable() );
}
@ -393,7 +393,7 @@ public class ToOneBinder {
if ( notFoundAction != null ) {
join.disableForeignKeyCreation();
}
for ( AnnotatedJoinColumn joinColumn : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn joinColumn : joinColumns.getJoinColumns() ) {
joinColumn.setExplicitTableName( join.getTable().getName() );
}
}
@ -493,16 +493,16 @@ public class ToOneBinder {
}
else {
final List<String> idColumnNames = new ArrayList<>();
final AnnotatedJoinColumn[] columns = joinColumns.getColumns();
if ( identifier.getColumnSpan() != columns.length ) {
final List<AnnotatedJoinColumn> columns = joinColumns.getJoinColumns();
if ( identifier.getColumnSpan() != columns.size() ) {
return false;
}
else {
for ( org.hibernate.mapping.Column currentColumn: identifier.getColumns() ) {
idColumnNames.add( currentColumn.getName() );
}
for ( AnnotatedJoinColumn col: columns ) {
if ( !idColumnNames.contains( col.getMappingColumn().getName() ) ) {
for ( AnnotatedJoinColumn column: columns ) {
if ( !idColumnNames.contains( column.getMappingColumn().getName() ) ) {
return false;
}
}

View File

@ -56,7 +56,6 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.AnnotatedColumns;
import org.hibernate.cfg.AnnotatedJoinColumn;
import org.hibernate.cfg.AnnotatedJoinColumns;
import org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass;
import org.hibernate.cfg.SetBasicValueTypeSecondPass;
@ -103,8 +102,8 @@ import static org.hibernate.cfg.annotations.HCANNHelper.findAnnotation;
*/
public class BasicValueBinder implements JdbcTypeIndicators {
// todo (6.0) : In light of how we want to build Types (specifically BasicTypes) moving forward this class should undergo major changes
// see the comments in #setType
// todo (6.0) : In light of how we want to build Types (specifically BasicTypes) moving
// forward this class should undergo major changes: see the comments in #setType
// but as always the "design" of these classes make it unclear exactly how to change it properly.
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, BasicValueBinder.class.getName() );
@ -1126,13 +1125,17 @@ public class BasicValueBinder implements JdbcTypeIndicators {
public void linkWithValue() {
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
final AnnotatedColumn firstColumn = columns.getColumns()[0];
final AnnotatedColumn firstColumn = columns.getColumns().get(0);
if ( !collector.isInSecondPass() && firstColumn.isNameDeferred() && referencedEntityName != null ) {
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( buildingContext );
joinColumns.setPropertyHolder( firstColumn.getPropertyHolder() );
joinColumns.setPropertyHolder( columns.getPropertyHolder() );
joinColumns.setPropertyName( firstColumn.getPropertyName() );
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns.getColumns() );
//TODO: resetting the parent here looks like a dangerous thing to do
// should we be cloning them first (the legacy code did not)
for ( AnnotatedColumn column : columns.getColumns() ) {
column.setParent( joinColumns );
}
collector.addSecondPass(
new PkDrivenByDefaultMapsIdSecondPass( referencedEntityName, joinColumns, basicValue )
);

View File

@ -174,7 +174,6 @@ import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
import static org.hibernate.internal.util.StringHelper.qualify;
import static org.hibernate.internal.util.collections.ArrayHelper.isEmpty;
/**
* Base class for binding different types of collections to Hibernate configuration objects.
@ -306,6 +305,7 @@ public abstract class CollectionBinder {
collectionBinder.setCache( property.getAnnotation( Cache.class ) );
collectionBinder.setPropertyHolder(propertyHolder);
final Cascade hibernateCascade = property.getAnnotation( Cascade.class );
final NotFound notFound = property.getAnnotation( NotFound.class );
if ( notFound != null ) {
@ -315,6 +315,7 @@ public abstract class CollectionBinder {
}
collectionBinder.setNotFoundAction( notFound.action() );
}
collectionBinder.setElementType( inferredData.getProperty().getElementClass() );
collectionBinder.setAccessType( inferredData.getDefaultAccess() );
@ -332,7 +333,8 @@ public abstract class CollectionBinder {
virtualProperty,
comment
);
final JoinColumn[] joinKeyColumns = mapKeyColumns(
final AnnotatedJoinColumns mapJoinColumns = buildJoinColumnsWithDefaultColumnSuffix(
mapKeyColumns(
propertyHolder,
inferredData,
entityBinder,
@ -340,9 +342,7 @@ public abstract class CollectionBinder {
property,
collectionBinder,
comment
);
final AnnotatedJoinColumns mapJoinColumns = buildJoinColumnsWithDefaultColumnSuffix(
joinKeyColumns,
),
comment,
null,
entityBinder.getSecondaryTables(),
@ -356,9 +356,16 @@ public abstract class CollectionBinder {
//potential element
collectionBinder.setEmbedded( property.isAnnotationPresent( Embedded.class ) );
collectionBinder.setElementColumns( elementColumns );
collectionBinder.setProperty(property);
collectionBinder.setProperty( property );
final String mappedBy = handleTargetEntity(
bindJoinedTableAssociation(
property,
context,
entityBinder,
collectionBinder,
propertyHolder,
inferredData,
handleTargetEntity(
propertyHolder,
inferredData,
context,
@ -369,32 +376,23 @@ public abstract class CollectionBinder {
elementCollectionAnn,
collectionBinder,
hibernateCascade
)
);
bindJoinedTableAssociation(
property,
context,
entityBinder,
collectionBinder,
propertyHolder,
inferredData,
mappedBy
);
final OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
final boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action();
final OnDelete onDelete = property.getAnnotation( OnDelete.class );
final boolean onDeleteCascade = onDelete != null && OnDeleteAction.CASCADE == onDelete.action();
collectionBinder.setCascadeDeleteEnabled( onDeleteCascade );
if ( isIdentifierMapper ) {
collectionBinder.setInsertable( false );
collectionBinder.setUpdatable( false );
}
if ( property.isAnnotationPresent( CollectionId.class ) ) { //do not compute the generators unless necessary
HashMap<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
localGenerators.putAll( AnnotationBinder.buildGenerators(property, context) );
final HashMap<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
localGenerators.putAll( AnnotationBinder.buildGenerators( property, context ) );
collectionBinder.setLocalGenerators( localGenerators );
}
collectionBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass );
collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() );
collectionBinder.bind();
}
@ -419,7 +417,7 @@ public abstract class CollectionBinder {
final String mappedBy;
final ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();
if ( oneToManyAnn != null ) {
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn column : joinColumns.getJoinColumns() ) {
if ( column.isSecondary() ) {
//TODO: fix the error message
throw new NotYetImplementedException( "Collections having FK in secondary table" );
@ -435,7 +433,7 @@ public abstract class CollectionBinder {
collectionBinder.setOneToMany( true );
}
else if ( elementCollectionAnn != null ) {
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn column : joinColumns.getJoinColumns() ) {
if ( column.isSecondary() ) {
//TODO: fix the error message
throw new NotYetImplementedException( "Collections having FK in secondary table" );
@ -1499,8 +1497,8 @@ public abstract class CollectionBinder {
&& !reversePropertyInJoin
&& oneToMany
&& !isExplicitAssociationTable
&& ( joinColumns.getColumns()[0].isImplicit() && hasMappedBy() //implicit @JoinColumn
|| !foreignJoinColumns.getColumns()[0].isImplicit() ) //this is an explicit @JoinColumn
&& ( joinColumns.getJoinColumns().get(0).isImplicit() && hasMappedBy() //implicit @JoinColumn
|| !foreignJoinColumns.getJoinColumns().get(0).isImplicit() ) //this is an explicit @JoinColumn
) {
//this is a foreign key
bindOneToManySecondPass( persistentClasses );
@ -1546,9 +1544,7 @@ public abstract class CollectionBinder {
final Map<String, Join> joins = buildingContext.getMetadataCollector().getJoins( referencedEntityName );
foreignJoinColumns.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
for ( AnnotatedJoinColumn column : foreignJoinColumns.getColumns() ) {
column.setJoins( joins );
}
foreignJoinColumns.setJoins( joins );
collection.setCollectionTable( foreignJoinColumns.getTable() );
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Mapping collection: %s -> %s", collection.getRole(), collection.getCollectionTable().getName() );
@ -1572,7 +1568,7 @@ public abstract class CollectionBinder {
final PersistentClass referenced = collector.getEntityBinding( entityName );
final Backref backref = new Backref();
final String backrefName = '_' + foreignJoinColumns.getPropertyName()
+ '_' + foreignJoinColumns.getColumns()[0].getLogicalColumnName()
+ '_' + foreignJoinColumns.getColumns().get(0).getLogicalColumnName()
+ "Backref";
backref.setName( backrefName );
backref.setUpdateable( false);
@ -1856,10 +1852,10 @@ public abstract class CollectionBinder {
final DependantValue key = new DependantValue( buildingContext, collection.getCollectionTable(), keyValue );
key.setTypeName( null );
final AnnotatedJoinColumn[] columns = joinColumns.getColumns();
final List<AnnotatedColumn> columns = joinColumns.getColumns();
checkPropertyConsistency( columns, collection.getOwnerEntityName() );
key.setNullable( columns.length == 0 || columns[0].isNullable() );
key.setUpdateable( columns.length == 0 || columns[0].isUpdatable() );
key.setNullable( columns.isEmpty() || columns.get(0).isNullable() );
key.setUpdateable( columns.isEmpty() || columns.get(0).isUpdatable() );
key.setCascadeDeleteEnabled( cascadeDeleteEnabled );
collection.setKey( key );
@ -1958,7 +1954,7 @@ public abstract class CollectionBinder {
}
private void overrideReferencedPropertyName(Collection collection, AnnotatedJoinColumns joinColumns) {
if ( hasMappedBy() && joinColumns.getColumns().length > 0 ) {
if ( hasMappedBy() && !joinColumns.getColumns().isEmpty() ) {
final String entityName = joinColumns.getManyToManyOwnerSideEntityName() != null
? "inverse__" + joinColumns.getManyToManyOwnerSideEntityName()
: joinColumns.getPropertyHolder().getEntityName();
@ -2199,22 +2195,21 @@ public abstract class CollectionBinder {
String defaultName,
Long defaultLength,
MetadataBuildingContext context) {
if ( elementColumns == null || isEmpty( elementColumns.getColumns() ) ) {
if ( elementColumns == null || elementColumns.getColumns().isEmpty() ) {
final AnnotatedColumns columns = new AnnotatedColumns();
columns.setBuildingContext( context );
final AnnotatedColumn column = new AnnotatedColumn();
column.setLogicalColumnName( defaultName );
if ( defaultLength!=null ) {
if ( defaultLength != null ) {
column.setLength( defaultLength );
}
column.setImplicit( false );
//not following the spec but more clean
column.setNullable( true );
//TODO create an EMPTY_JOINS collection
column.setJoins( new HashMap<>() );
column.setBuildingContext( context );
// column.setContext( context );
column.setParent( columns );
column.bind();
final AnnotatedColumns result = new AnnotatedColumns();
result.setColumns( new AnnotatedColumn[] { column } );
elementColumns = result;
elementColumns = columns;
}
//override the table
elementColumns.setTable( collection.getCollectionTable() );
@ -2560,7 +2555,7 @@ public abstract class CollectionBinder {
if ( hasMappedBy() ) {
final Property property = targetEntity.getRecursiveProperty( mappedBy );
final List<Selectable> mappedByColumns = mappedByColumns( targetEntity, property );
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
for ( Selectable selectable: mappedByColumns ) {
firstColumn.linkValueUsingAColumnCopy( (Column) selectable, value );
}

View File

@ -215,7 +215,7 @@ public class EntityBinder {
//TODO: be more strict with secondary table allowance (not for ids, not for secondary table join columns etc)
final InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
final PersistentClass superEntity = getSuperEntity( clazzToProcess, inheritanceStatePerClass, context, inheritanceState );
detectedAttributeOverrideProblem(clazzToProcess, superEntity );
detectedAttributeOverrideProblem( clazzToProcess, superEntity );
final PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity, context);
final EntityBinder entityBinder = new EntityBinder( clazzToProcess, persistentClass, context );
@ -789,11 +789,13 @@ public class EntityBinder {
if ( discriminatorColumn == null ) {
throw new AssertionFailure( "discriminator column should have been built" );
}
discriminatorColumn.setJoins( secondaryTables );
// discriminatorColumn.setPropertyHolder( propertyHolder );
final AnnotatedColumns columns = new AnnotatedColumns();
columns.setColumns( new AnnotatedColumn[] { discriminatorColumn } );
columns.setPropertyHolder( propertyHolder );
columns.setBuildingContext( context );
columns.setJoins( secondaryTables );
// discriminatorColumn.setJoins( secondaryTables );
// discriminatorColumn.setPropertyHolder( propertyHolder );
discriminatorColumn.setParent( columns );
final BasicValue discriminatorColumnBinding = new BasicValue( context, rootClass.getTable() );
rootClass.setDiscriminator( discriminatorColumnBinding );
@ -817,16 +819,19 @@ public class EntityBinder {
InheritanceState inheritanceState,
EntityBinder entityBinder) {
DiscriminatorColumn discAnn = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
DiscriminatorType discriminatorType = discAnn != null ? discAnn.discriminatorType() : DiscriminatorType.STRING;
final DiscriminatorColumn discriminatorColumn = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
final DiscriminatorType discriminatorType = discriminatorColumn != null
? discriminatorColumn.discriminatorType()
: DiscriminatorType.STRING;
DiscriminatorFormula discFormulaAnn = getOverridableAnnotation( clazzToProcess, DiscriminatorFormula.class, context );
final DiscriminatorFormula discriminatorFormula =
getOverridableAnnotation( clazzToProcess, DiscriminatorFormula.class, context );
final boolean isRoot = !inheritanceState.hasParents();
final AnnotatedDiscriminatorColumn discriminatorColumn = isRoot
? buildDiscriminatorColumn( discriminatorType, discAnn, discFormulaAnn, context )
final AnnotatedDiscriminatorColumn discriminator = isRoot
? buildDiscriminatorColumn( discriminatorType, discriminatorColumn, discriminatorFormula, context )
: null;
if ( discAnn != null && !isRoot ) {
if ( discriminatorColumn != null && !isRoot ) {
//TODO: shouldn't this be an error?!
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
}
@ -836,13 +841,13 @@ public class EntityBinder {
: null;
entityBinder.setDiscriminatorValue( discriminatorValue );
DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
final DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
if ( discriminatorOptions != null) {
entityBinder.setForceDiscriminator( discriminatorOptions.force() );
entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() );
}
return discriminatorColumn;
return discriminator;
}
/**
@ -997,59 +1002,63 @@ public class EntityBinder {
InheritanceState inheritanceState,
PersistentClass superEntity) {
AnnotatedJoinColumn[] inheritanceJoinedColumns = null;
final boolean hasJoinedColumns = inheritanceState.hasParents()
&& InheritanceType.JOINED == inheritanceState.getType();
if ( hasJoinedColumns ) {
//@Inheritance(JOINED) subclass need to link back to the super entity
final PrimaryKeyJoinColumns jcsAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class );
boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0;
if ( explicitInheritanceJoinedColumns ) {
int nbrOfInhJoinedColumns = jcsAnn.value().length;
PrimaryKeyJoinColumn jcAnn;
inheritanceJoinedColumns = new AnnotatedJoinColumn[nbrOfInhJoinedColumns];
for ( int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++ ) {
jcAnn = jcsAnn.value()[colIndex];
inheritanceJoinedColumns[colIndex] = buildJoinColumn(
jcAnn,
null,
superEntity.getIdentifier(),
null,
null,
context
);
}
}
else {
final PrimaryKeyJoinColumn jcAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class );
inheritanceJoinedColumns = new AnnotatedJoinColumn[1];
inheritanceJoinedColumns[0] = buildJoinColumn(
jcAnn,
null,
superEntity.getIdentifier(),
null,
null,
context
);
}
LOG.trace( "Subclass joined column(s) created" );
return subclassJoinColumns( clazzToProcess, superEntity, context );
}
else {
if ( clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumns.class )
|| clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumn.class ) ) {
LOG.invalidPrimaryKeyJoinColumnAnnotation( clazzToProcess.getName() );
}
}
if ( inheritanceJoinedColumns == null ) {
return null;
}
else {
}
private static AnnotatedJoinColumns subclassJoinColumns(
XClass clazzToProcess,
PersistentClass superEntity,
MetadataBuildingContext context) {
//@Inheritance(JOINED) subclass need to link back to the super entity
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setColumns( inheritanceJoinedColumns );
return joinColumns;
final PrimaryKeyJoinColumns primaryKeyJoinColumns = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class );
if ( primaryKeyJoinColumns != null ) {
final PrimaryKeyJoinColumn[] columns = primaryKeyJoinColumns.value();
if ( columns.length > 0 ) {
for ( PrimaryKeyJoinColumn column : columns ) {
buildJoinColumn(
column,
null,
superEntity.getIdentifier(),
joinColumns,
context
);
}
}
else {
buildJoinColumn(
clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class ),
null,
superEntity.getIdentifier(),
joinColumns,
context
);
}
}
else {
buildJoinColumn(
clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class ),
null,
superEntity.getIdentifier(),
joinColumns,
context
);
}
LOG.trace( "Subclass joined column(s) created" );
return joinColumns;
}
private static PersistentClass getSuperEntity(
XClass clazzToProcess,
@ -1741,7 +1750,7 @@ public class EntityBinder {
public void finalSecondaryTableBinding(PropertyHolder propertyHolder) {
// This operation has to be done after the id definition of the persistence class.
// ie after the properties parsing
Iterator<Object> joinColumns = secondaryTableJoins.values().iterator();
final Iterator<Object> joinColumns = secondaryTableJoins.values().iterator();
for ( Map.Entry<String, Join> entrySet : secondaryTables.entrySet() ) {
if ( !secondaryTablesFromAnnotation.containsKey( entrySet.getKey() ) ) {
createPrimaryColumnsToSecondaryTable( joinColumns.next(), propertyHolder, entrySet.getValue() );
@ -1771,56 +1780,52 @@ public class EntityBinder {
? createDefaultJoinColumn( propertyHolder )
: createJoinColumns( propertyHolder, pkColumnsAnn, joinColumnsAnn );
for ( AnnotatedJoinColumn joinColumn : annotatedJoinColumns.getColumns() ) {
for ( AnnotatedJoinColumn joinColumn : annotatedJoinColumns.getJoinColumns() ) {
joinColumn.forceNotNull();
}
bindJoinToPersistentClass( join, annotatedJoinColumns, context );
}
private AnnotatedJoinColumns createDefaultJoinColumn(PropertyHolder propertyHolder) {
final AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[1];
annotatedJoinColumns[0] = buildJoinColumn(
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setJoins( secondaryTables );
joinColumns.setPropertyHolder( propertyHolder );
buildJoinColumn(
null,
null,
persistentClass.getIdentifier(),
secondaryTables,
propertyHolder,
joinColumns,
context
);
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setColumns( annotatedJoinColumns );
return joinColumns;
}
private AnnotatedJoinColumns createJoinColumns(
PropertyHolder propertyHolder,
PrimaryKeyJoinColumn[] pkColumnsAnn,
JoinColumn[] joinColumnsAnn) {
final int joinColumnCount = pkColumnsAnn != null ? pkColumnsAnn.length : joinColumnsAnn.length;
PrimaryKeyJoinColumn[] primaryKeyJoinColumns,
JoinColumn[] joinColumns) {
final int joinColumnCount = primaryKeyJoinColumns != null ? primaryKeyJoinColumns.length : joinColumns.length;
if ( joinColumnCount == 0 ) {
return createDefaultJoinColumn( propertyHolder );
}
else {
final AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[joinColumnCount];
for (int colIndex = 0; colIndex < joinColumnCount; colIndex++) {
final PrimaryKeyJoinColumn pkJoinAnn = pkColumnsAnn != null ? pkColumnsAnn[colIndex] : null;
final JoinColumn joinAnn = joinColumnsAnn != null ? joinColumnsAnn[colIndex] : null;
annotatedJoinColumns[colIndex] = buildJoinColumn(
pkJoinAnn,
joinAnn,
final AnnotatedJoinColumns columns = new AnnotatedJoinColumns();
columns.setBuildingContext( context );
columns.setJoins( secondaryTables );
columns.setPropertyHolder( propertyHolder );
for ( int colIndex = 0; colIndex < joinColumnCount; colIndex++ ) {
final PrimaryKeyJoinColumn primaryKeyJoinColumn = primaryKeyJoinColumns != null ? primaryKeyJoinColumns[colIndex] : null;
final JoinColumn joinColumn = joinColumns != null ? joinColumns[colIndex] : null;
buildJoinColumn(
primaryKeyJoinColumn,
joinColumn,
persistentClass.getIdentifier(),
secondaryTables,
propertyHolder,
columns,
context
);
}
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setColumns( annotatedJoinColumns );
return joinColumns;
return columns;
}
}

View File

@ -12,8 +12,6 @@ import java.util.function.Supplier;
import org.hibernate.MappingException;
import org.hibernate.annotations.OrderBy;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.cfg.AnnotatedColumn;
import org.hibernate.cfg.AnnotatedColumns;
import org.hibernate.cfg.CollectionSecondPass;
import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.PropertyHolderBuilder;
@ -86,13 +84,10 @@ public class ListBinder extends CollectionBinder {
if ( !listValueMapping.isOneToMany() ) {
indexColumn.forceNotNull();
}
// indexColumn.setPropertyHolder( valueHolder );
final AnnotatedColumns columns = new AnnotatedColumns();
columns.setColumns( new AnnotatedColumn[] { indexColumn } );
columns.setPropertyHolder( valueHolder );
indexColumn.getParent().setPropertyHolder( valueHolder );
final BasicValueBinder valueBinder = new BasicValueBinder( BasicValueBinder.Kind.LIST_INDEX, buildingContext );
valueBinder.setColumns( columns );
valueBinder.setColumns( indexColumn.getParent() );
valueBinder.setReturnedClassName( Integer.class.getName() );
valueBinder.setType( property, getElementType(), null, null );
// valueBinder.setExplicitType( "integer" );

View File

@ -100,8 +100,7 @@ public class MapBinder extends CollectionBinder {
property,
isEmbedded,
mapKeyColumns,
mapKeyManyToManyColumns,
inverseJoinColumns != null ? inverseJoinColumns.getPropertyName() : null
mapKeyManyToManyColumns
);
makeOneToManyMapKeyColumnNullableIfNotInProperty( property );
}
@ -157,8 +156,7 @@ public class MapBinder extends CollectionBinder {
XProperty property,
boolean isEmbedded,
AnnotatedColumns mapKeyColumns,
AnnotatedJoinColumns mapKeyManyToManyColumns,
String targetPropertyName) {
AnnotatedJoinColumns mapKeyManyToManyColumns) {
if ( mapKeyPropertyName != null ) {
//this is an EJB3 @MapKey
handleExplicitMapKey( elementType, persistentClasses, mapKeyPropertyName );
@ -205,7 +203,7 @@ public class MapBinder extends CollectionBinder {
//FIXME pass the Index Entity JoinColumns
if ( !collection.isOneToMany() ) {
//index column should not be null
for ( AnnotatedJoinColumn column : mapKeyManyToManyColumns.getColumns() ) {
for ( AnnotatedJoinColumn column : mapKeyManyToManyColumns.getJoinColumns() ) {
column.forceNotNull();
}
}
@ -243,7 +241,7 @@ public class MapBinder extends CollectionBinder {
throw new AnnotationException( "Association '" + safeCollectionRole()
+ "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
}
final Property mapProperty = findPropertyByName( associatedClass, mapKeyPropertyName);
final Property mapProperty = findPropertyByName( associatedClass, mapKeyPropertyName );
if ( mapProperty == null ) {
throw new AnnotationException( "Map key property '" + mapKeyPropertyName
+ "' not found in target entity '" + associatedClass.getEntityName() + "'" );
@ -274,7 +272,7 @@ public class MapBinder extends CollectionBinder {
// 'propertyHolder' is the PropertyHolder for the owner of the collection
// 'holder' is the CollectionPropertyHolder.
// 'property' is the collection XProperty
propertyHolder.startingProperty(property);
propertyHolder.startingProperty( property );
holder.prepare(property);
return holder;
}
@ -301,9 +299,9 @@ public class MapBinder extends CollectionBinder {
String mapKeyType,
org.hibernate.mapping.Map map) {
final ManyToOne element;
element = new ManyToOne(context, map.getCollectionTable() );
element = new ManyToOne( context, map.getCollectionTable() );
map.setIndex( element );
element.setReferencedEntityName(mapKeyType);
element.setReferencedEntityName( mapKeyType );
//element.setFetchMode( fetchMode );
//element.setLazy( fetchMode != FetchMode.JOIN );
//make the second join non lazy
@ -344,11 +342,8 @@ public class MapBinder extends CollectionBinder {
AnnotatedClassType classType,
CollectionPropertyHolder holder,
AccessType accessType) {
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType(
property,
keyClass,
buildingContext
);
final Class<? extends CompositeUserType<?>> compositeUserType =
resolveCompositeUserType( property, keyClass, buildingContext );
if ( AnnotatedClassType.EMBEDDABLE == classType || compositeUserType != null ) {
final EntityBinder entityBinder = new EntityBinder();
@ -375,7 +370,7 @@ public class MapBinder extends CollectionBinder {
}
else {
final BasicValueBinder elementBinder = new BasicValueBinder( BasicValueBinder.Kind.MAP_KEY, buildingContext );
elementBinder.setReturnedClassName(mapKeyType);
elementBinder.setReturnedClassName( mapKeyType );
final AnnotatedColumns keyColumns = createElementColumnsIfNecessary(
collection,
mapKeyColumns,
@ -390,10 +385,10 @@ public class MapBinder extends CollectionBinder {
property,
keyClass,
collection.getOwnerEntityName(),
holder.mapKeyAttributeConverterDescriptor(property, keyClass)
holder.mapKeyAttributeConverterDescriptor( property, keyClass )
);
elementBinder.setPersistentClassName( propertyHolder.getEntityName() );
elementBinder.setAccessType(accessType);
elementBinder.setAccessType( accessType );
map.setIndex( elementBinder.make() );
}
}

View File

@ -8,8 +8,6 @@ package org.hibernate.cfg.annotations;
import jakarta.persistence.NamedEntityGraph;
import org.hibernate.internal.util.StringHelper;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/**

View File

@ -130,7 +130,7 @@ public class PropertyBinder {
}
public void setColumns(AnnotatedColumns columns) {
final AnnotatedColumn firstColumn = columns.getColumns()[0];
final AnnotatedColumn firstColumn = columns.getColumns().get(0);
insertable = firstColumn.isInsertable();
updatable = firstColumn.isUpdatable();
//consistency is checked later when we know the property name

View File

@ -548,7 +548,7 @@ public class TableBinder {
associatedClass = holder == null ? null : holder.getPersistentClass();
}
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
if ( joinColumns.hasMappedBy() ) {
// use the columns of the property referenced by mappedBy
// copy them and link the copy to the actual value
@ -592,12 +592,12 @@ public class TableBinder {
SimpleValue value,
PersistentClass associatedClass) {
//implicit case, we hope PK and FK columns are in the same order
if ( joinColumns.getColumns().length != referencedEntity.getIdentifier().getColumnSpan() ) {
if ( joinColumns.getColumns().size() != referencedEntity.getIdentifier().getColumnSpan() ) {
// TODO: what about secondary tables?? associatedClass is null?
throw new AnnotationException(
"An association that targets entity '" + referencedEntity.getEntityName()
+ "' from entity '" + associatedClass.getEntityName()
+ "' has " + joinColumns.getColumns().length + " '@JoinColumn's but the primary key has "
+ "' has " + joinColumns.getColumns().size() + " '@JoinColumn's but the primary key has "
+ referencedEntity.getIdentifier().getColumnSpan() + " columns"
);
}
@ -631,7 +631,7 @@ public class TableBinder {
boolean match = false;
// for each PK column, find the associated FK column.
final String quotedName = column.getQuotedName( dialect );
for ( AnnotatedJoinColumn joinColumn : joinColumns.getColumns() ) {
for ( AnnotatedJoinColumn joinColumn : joinColumns.getJoinColumns() ) {
final String referencedColumn = buildingContext.getMetadataCollector()
.getPhysicalColumnName( referencedEntity.getTable(), joinColumn.getReferencedColumn() );
// in JPA 2 referencedColumnName is case-insensitive
@ -704,7 +704,7 @@ public class TableBinder {
? referencedEntity.getKey().getColumns()
: referencedEntity.getIdentifier().getColumns();
for ( Column column: idColumns ) {
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
firstColumn.linkValueUsingDefaultColumnNaming( column, referencedEntity, value);
firstColumn.overrideFromReferencedColumnIfNecessary( column );
}
@ -715,7 +715,7 @@ public class TableBinder {
SimpleValue value,
PersistentClass associatedClass,
String mappedByProperty) {
final AnnotatedJoinColumn firstColumn = joinColumns.getColumns()[0];
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
for ( Column column: mappedByColumns( associatedClass, mappedByProperty ) ) {
firstColumn.overrideFromReferencedColumnIfNecessary( column );
firstColumn.linkValueUsingAColumnCopy( column, value);
@ -744,9 +744,9 @@ public class TableBinder {
AnnotatedJoinColumns joinColumns,
SimpleValue simpleValue) {
final List<Column> valueColumns = value.getColumns();
final AnnotatedJoinColumn[] columns = joinColumns.getColumns();
for (int i = 0; i < columns.length; i++ ) {
final AnnotatedJoinColumn joinColumn = columns[i];
final List<AnnotatedJoinColumn> columns = joinColumns.getJoinColumns();
for ( int i = 0; i < columns.size(); i++ ) {
final AnnotatedJoinColumn joinColumn = columns.get(i);
final Column synthCol = valueColumns.get(i);
if ( joinColumn.isNameDeferred() ) {
//this has to be the default value

View File

@ -24,7 +24,7 @@ public class NullableDiscriminatorColumnSecondPass implements SecondPass {
@Override
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
PersistentClass rootPersistenceClass = persistentClasses.get( rootEntityName );
final PersistentClass rootPersistenceClass = persistentClasses.get( rootEntityName );
if ( hasNullDiscriminatorValue( rootPersistenceClass ) ) {
for ( Selectable selectable: rootPersistenceClass.getDiscriminator().getSelectables() ) {
if ( selectable instanceof Column ) {

View File

@ -106,7 +106,7 @@ public class SqlExceptionHelper {
*/
public JDBCException convert(SQLException sqlException, String message, String sql) {
logExceptions( sqlException, message + " [" + sql + "]" );
return sqlExceptionConverter.convert( sqlException, message, sql );
return sqlExceptionConverter.convert( sqlException, message + " [" + sqlException.getMessage() + "]", sql );
}
/**

View File

@ -26,7 +26,7 @@ public class BankAccount {
@GeneratedValue
private long id;
@OneToMany(mappedBy = "account", cascade = { CascadeType.ALL })
@OneToMany(mappedBy = "account", cascade = CascadeType.ALL)
@OrderColumn(name = "transactions_index")
private List<Transaction> transactions;