introduce AnnotatedColumns
This commit is contained in:
parent
653bf987bd
commit
ec336f3a23
|
@ -3275,9 +3275,9 @@ public class ModelBinder {
|
|||
&& !collectionBinding.isInverse()
|
||||
&& !collectionBinding.getKey().isNullable() ) {
|
||||
// for non-inverse one-to-many, with a not-null fk, add a backref!
|
||||
String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
||||
PersistentClass referenced = getReferencedEntityBinding( entityName );
|
||||
Backref prop = new Backref();
|
||||
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
||||
final PersistentClass referenced = getReferencedEntityBinding( entityName );
|
||||
final Backref prop = new Backref();
|
||||
prop.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "Backref" );
|
||||
prop.setUpdateable( false );
|
||||
prop.setSelectable( false );
|
||||
|
@ -3298,13 +3298,13 @@ public class ModelBinder {
|
|||
|
||||
protected void bindCollectionKey() {
|
||||
final PluralAttributeKeySource keySource = getPluralAttributeSource().getKeySource();
|
||||
final String propRef = keySource.getReferencedPropertyName();
|
||||
getCollectionBinding().setReferencedPropertyName( propRef );
|
||||
final String referencedPropertyName = keySource.getReferencedPropertyName();
|
||||
getCollectionBinding().setReferencedPropertyName( referencedPropertyName );
|
||||
|
||||
final PersistentClass owner = getCollectionBinding().getOwner();
|
||||
final KeyValue keyVal = propRef == null
|
||||
final KeyValue keyVal = referencedPropertyName == null
|
||||
? owner.getIdentifier()
|
||||
: (KeyValue) owner.getRecursiveProperty( propRef ).getValue();
|
||||
: (KeyValue) owner.getRecursiveProperty( referencedPropertyName ).getValue();
|
||||
final DependantValue key = new DependantValue(
|
||||
mappingDocument,
|
||||
getCollectionBinding().getCollectionTable(),
|
||||
|
|
|
@ -42,6 +42,7 @@ import static org.hibernate.cfg.BinderHelper.getPath;
|
|||
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
||||
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
|
||||
/**
|
||||
* A mapping to a column, logically representing a
|
||||
|
@ -67,8 +68,9 @@ public class AnnotatedColumn {
|
|||
private Column mappingColumn;
|
||||
private boolean insertable = true;
|
||||
private boolean updatable = true;
|
||||
private String explicitTableName;
|
||||
private String explicitTableName; // the JPA @Column annotation lets you specify a table name
|
||||
protected Map<String, Join> joins;
|
||||
@Deprecated // use AnnotatedColumns.propertyHolder
|
||||
protected PropertyHolder propertyHolder;
|
||||
private boolean isImplicit;
|
||||
public String sqlType;
|
||||
|
@ -81,7 +83,6 @@ public class AnnotatedColumn {
|
|||
private boolean nullable = true;
|
||||
private String formulaString;
|
||||
private Formula formula;
|
||||
private Table table;
|
||||
private String readExpression;
|
||||
private String writeExpression;
|
||||
|
||||
|
@ -91,8 +92,10 @@ public class AnnotatedColumn {
|
|||
private String comment;
|
||||
private String checkConstraint;
|
||||
|
||||
public void setTable(Table table) {
|
||||
this.table = table;
|
||||
private AnnotatedColumns parent;
|
||||
|
||||
void setParent(AnnotatedColumns parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getLogicalColumnName() {
|
||||
|
@ -123,23 +126,16 @@ public class AnnotatedColumn {
|
|||
return isNotEmpty( formulaString );
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public String getFormulaString() {
|
||||
return formulaString;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public String getExplicitTableName() {
|
||||
return explicitTableName;
|
||||
}
|
||||
|
||||
public void setExplicitTableName(String explicitTableName) {
|
||||
if ( "``".equals( explicitTableName ) ) {
|
||||
this.explicitTableName = "";
|
||||
}
|
||||
else {
|
||||
this.explicitTableName = explicitTableName;
|
||||
}
|
||||
this.explicitTableName = "``".equals( explicitTableName ) ? "" : explicitTableName;
|
||||
}
|
||||
|
||||
public void setFormula(String formula) {
|
||||
|
@ -371,8 +367,8 @@ public class AnnotatedColumn {
|
|||
public boolean isCollectionElement() {
|
||||
// if the propertyHolder is a collection, assume the
|
||||
// @Column refers to the element column
|
||||
return !propertyHolder.isComponent()
|
||||
&& !propertyHolder.isEntity();
|
||||
return !getPropertyHolder().isComponent()
|
||||
&& !getPropertyHolder().isEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -426,9 +422,10 @@ public class AnnotatedColumn {
|
|||
}
|
||||
|
||||
public PropertyHolder getPropertyHolder() {
|
||||
return propertyHolder;
|
||||
return propertyHolder; //TODO: change this to delegate to the parent
|
||||
}
|
||||
|
||||
@Deprecated // use AnnotatedColumns.setPropertyHolder() instead
|
||||
public void setPropertyHolder(PropertyHolder propertyHolder) {
|
||||
this.propertyHolder = propertyHolder;
|
||||
}
|
||||
|
@ -437,12 +434,16 @@ public class AnnotatedColumn {
|
|||
this.mappingColumn = mappingColumn;
|
||||
}
|
||||
|
||||
//TODO: move this operation to AnnotatedColumns!!
|
||||
public void linkWithValue(SimpleValue value) {
|
||||
if ( formula != null ) {
|
||||
value.addFormula( formula );
|
||||
}
|
||||
else {
|
||||
table = value.getTable();
|
||||
final Table table = value.getTable();
|
||||
if ( parent != null ) {
|
||||
parent.setTableInternal( table );
|
||||
}
|
||||
getMappingColumn().setValue( value );
|
||||
value.addColumn( getMappingColumn(), insertable, updatable );
|
||||
table.addColumn( getMappingColumn() );
|
||||
|
@ -494,31 +495,25 @@ public class AnnotatedColumn {
|
|||
* @throws AnnotationException missing secondary table
|
||||
*/
|
||||
public Table getTable() {
|
||||
if ( table != null ) {
|
||||
return table;
|
||||
}
|
||||
else if ( isSecondary() ) {
|
||||
return getJoin().getTable();
|
||||
}
|
||||
else {
|
||||
return propertyHolder.getTable();
|
||||
}
|
||||
return parent.getTable();
|
||||
}
|
||||
|
||||
//TODO: move to AnnotatedColumns
|
||||
public boolean isSecondary() {
|
||||
if ( propertyHolder == null ) {
|
||||
throw new AssertionFailure( "Should not call getTable() on column w/o persistent class defined" );
|
||||
throw new AssertionFailure( "Should not call isSecondary() on column w/o persistent class defined" );
|
||||
}
|
||||
|
||||
return isNotEmpty( explicitTableName )
|
||||
&& !propertyHolder.getTable().getName().equals( explicitTableName );
|
||||
&& !getPropertyHolder().getTable().getName().equals( explicitTableName );
|
||||
}
|
||||
|
||||
//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 );
|
||||
final String physicalTableName = getBuildingContext().getMetadataCollector()
|
||||
.getPhysicalTableName( explicitTableName );
|
||||
if ( physicalTableName != null ) {
|
||||
join = joins.get( physicalTableName );
|
||||
}
|
||||
|
@ -526,7 +521,7 @@ public class AnnotatedColumn {
|
|||
|
||||
if ( join == null ) {
|
||||
throw new AnnotationException(
|
||||
"Secondary table '" + explicitTableName + "' for property '" + propertyHolder.getClassName()
|
||||
"Secondary table '" + explicitTableName + "' for property '" + getPropertyHolder().getClassName()
|
||||
+ "' is not declared (use '@SecondaryTable' to declare the secondary table)"
|
||||
);
|
||||
}
|
||||
|
@ -544,7 +539,7 @@ public class AnnotatedColumn {
|
|||
mappingColumn.setNullable( false );
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildFormulaFromAnnotation(
|
||||
public static AnnotatedColumns buildFormulaFromAnnotation(
|
||||
org.hibernate.annotations.Formula formulaAnn,
|
||||
Comment commentAnn,
|
||||
Nullability nullability,
|
||||
|
@ -564,7 +559,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnFromNoAnnotation(
|
||||
public static AnnotatedColumns buildColumnFromNoAnnotation(
|
||||
Comment commentAnn,
|
||||
Nullability nullability,
|
||||
PropertyHolder propertyHolder,
|
||||
|
@ -582,7 +577,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnFromAnnotation(
|
||||
public static AnnotatedColumns buildColumnFromAnnotation(
|
||||
jakarta.persistence.Column column,
|
||||
Comment commentAnn,
|
||||
Nullability nullability,
|
||||
|
@ -602,7 +597,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnsFromAnnotations(
|
||||
public static AnnotatedColumns buildColumnsFromAnnotations(
|
||||
jakarta.persistence.Column[] columns,
|
||||
Comment commentAnn,
|
||||
Nullability nullability,
|
||||
|
@ -623,7 +618,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnsFromAnnotations(
|
||||
public static AnnotatedColumns buildColumnsFromAnnotations(
|
||||
jakarta.persistence.Column[] columns,
|
||||
Comment commentAnn,
|
||||
Nullability nullability,
|
||||
|
@ -645,7 +640,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnOrFormulaFromAnnotation(
|
||||
public static AnnotatedColumns buildColumnOrFormulaFromAnnotation(
|
||||
jakarta.persistence.Column column,
|
||||
org.hibernate.annotations.Formula formulaAnn,
|
||||
Comment commentAnn,
|
||||
|
@ -667,7 +662,7 @@ public class AnnotatedColumn {
|
|||
);
|
||||
}
|
||||
|
||||
public static AnnotatedColumn[] buildColumnsOrFormulaFromAnnotation(
|
||||
public static AnnotatedColumns buildColumnsOrFormulaFromAnnotation(
|
||||
jakarta.persistence.Column[] columns,
|
||||
org.hibernate.annotations.Formula formulaAnn,
|
||||
Comment comment,
|
||||
|
@ -685,10 +680,13 @@ public class AnnotatedColumn {
|
|||
formulaColumn.setBuildingContext( context );
|
||||
formulaColumn.setPropertyHolder( propertyHolder );
|
||||
formulaColumn.bind();
|
||||
return new AnnotatedColumn[] { formulaColumn };
|
||||
final AnnotatedColumns result = new AnnotatedColumns();
|
||||
result.setPropertyHolder( propertyHolder );
|
||||
result.setColumns(new AnnotatedColumn[] {formulaColumn});
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
jakarta.persistence.Column[] actualCols = overrideColumns( columns, propertyHolder, inferredData);
|
||||
final jakarta.persistence.Column[] actualCols = overrideColumns( columns, propertyHolder, inferredData );
|
||||
if ( actualCols == null ) {
|
||||
return buildImplicitColumn(
|
||||
inferredData,
|
||||
|
@ -719,7 +717,7 @@ public class AnnotatedColumn {
|
|||
PropertyHolder propertyHolder,
|
||||
PropertyData inferredData ) {
|
||||
final jakarta.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(
|
||||
StringHelper.qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
|
||||
qualify( propertyHolder.getPath(), inferredData.getPropertyName() )
|
||||
);
|
||||
if ( overriddenCols != null ) {
|
||||
//check for overridden first
|
||||
|
@ -739,7 +737,7 @@ public class AnnotatedColumn {
|
|||
}
|
||||
}
|
||||
|
||||
private static AnnotatedColumn[] buildExplicitColumns(
|
||||
private static AnnotatedColumns buildExplicitColumns(
|
||||
Comment comment,
|
||||
PropertyHolder propertyHolder,
|
||||
PropertyData inferredData,
|
||||
|
@ -775,7 +773,10 @@ public class AnnotatedColumn {
|
|||
tableName
|
||||
);
|
||||
}
|
||||
return columns;
|
||||
final AnnotatedColumns result = new AnnotatedColumns();
|
||||
result.setPropertyHolder(propertyHolder);
|
||||
result.setColumns(columns);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AnnotatedColumn buildColumn(
|
||||
|
@ -884,8 +885,8 @@ public class AnnotatedColumn {
|
|||
if ( inferredData != null ) {
|
||||
XProperty property = inferredData.getProperty();
|
||||
if ( property != null ) {
|
||||
if ( propertyHolder.isComponent() ) {
|
||||
processColumnTransformerExpressions( propertyHolder.getOverriddenColumnTransformer( logicalColumnName ) );
|
||||
if ( getPropertyHolder().isComponent() ) {
|
||||
processColumnTransformerExpressions( getPropertyHolder().getOverriddenColumnTransformer( logicalColumnName ) );
|
||||
}
|
||||
processColumnTransformerExpressions( property.getAnnotation( ColumnTransformer.class ) );
|
||||
ColumnTransformers annotations = property.getAnnotation( ColumnTransformers.class );
|
||||
|
@ -909,7 +910,7 @@ public class AnnotatedColumn {
|
|||
}
|
||||
}
|
||||
|
||||
private static AnnotatedColumn[] buildImplicitColumn(
|
||||
private static AnnotatedColumns buildImplicitColumn(
|
||||
PropertyData inferredData,
|
||||
String suffixForDefaultColumnName,
|
||||
Map<String, Join> secondaryTables,
|
||||
|
@ -917,8 +918,9 @@ public class AnnotatedColumn {
|
|||
Comment comment,
|
||||
Nullability nullability,
|
||||
MetadataBuildingContext context) {
|
||||
final AnnotatedColumn[] columns = new AnnotatedColumn[1];
|
||||
columns[0] = bindImplicitColumn(
|
||||
final AnnotatedColumns result = new AnnotatedColumns();
|
||||
result.setPropertyHolder( propertyHolder );
|
||||
final AnnotatedColumn column = bindImplicitColumn(
|
||||
inferredData,
|
||||
suffixForDefaultColumnName,
|
||||
secondaryTables,
|
||||
|
@ -927,7 +929,8 @@ public class AnnotatedColumn {
|
|||
nullability,
|
||||
context
|
||||
);
|
||||
return columns;
|
||||
result.setColumns( new AnnotatedColumn[] { column } );
|
||||
return result;
|
||||
}
|
||||
|
||||
private static AnnotatedColumn bindImplicitColumn(
|
||||
|
@ -968,9 +971,8 @@ public class AnnotatedColumn {
|
|||
}
|
||||
|
||||
public static void checkPropertyConsistency(AnnotatedColumn[] columns, String propertyName) {
|
||||
int nbrOfColumns = columns.length;
|
||||
if ( nbrOfColumns > 1 ) {
|
||||
for (int currentIndex = 1; currentIndex < nbrOfColumns; currentIndex++) {
|
||||
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() ) {
|
||||
throw new AnnotationException(
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.mapping.Table;
|
||||
|
||||
/**
|
||||
* A list of columns that are mapped to a single Java property
|
||||
* or field. This is a slightly uncomfortable abstraction here,
|
||||
* because this concept is arguably missing from JPA (where
|
||||
* there's no equivalent of the Hibernate-defined
|
||||
* {@link org.hibernate.annotations.Columns} annotation) and
|
||||
* so JPA lets each {@link jakarta.persistence.Column} specify
|
||||
* its own {@link jakarta.persistence.Column#table table}.
|
||||
* That leaves us having to enforce the requirement that every
|
||||
* column mapped to a given property must belong to the same
|
||||
* table.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class AnnotatedColumns {
|
||||
private AnnotatedColumn[] columns;
|
||||
private Table table;
|
||||
private PropertyHolder propertyHolder;
|
||||
|
||||
public void setColumns(AnnotatedColumn[] columns) {
|
||||
this.columns = columns;
|
||||
if ( columns != null ) {
|
||||
for ( AnnotatedColumn column : columns ) {
|
||||
column.setParent( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AnnotatedColumn[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public PropertyHolder getPropertyHolder() {
|
||||
return propertyHolder;
|
||||
}
|
||||
|
||||
public void setPropertyHolder(PropertyHolder propertyHolder) {
|
||||
this.propertyHolder = propertyHolder;
|
||||
}
|
||||
|
||||
public Table getTable() {
|
||||
if ( table != null ) {
|
||||
return table;
|
||||
}
|
||||
else {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTable(Table table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
void setTableInternal(Table table) {
|
||||
this.table = table;
|
||||
}
|
||||
}
|
|
@ -549,6 +549,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
|
||||
public void setParent(AnnotatedJoinColumns parent) {
|
||||
super.setParent( parent );
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ import static org.hibernate.internal.util.StringHelper.qualify;
|
|||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class AnnotatedJoinColumns {
|
||||
public class AnnotatedJoinColumns extends AnnotatedColumns {
|
||||
|
||||
private AnnotatedJoinColumn[] columns;
|
||||
private PropertyHolder propertyHolder;
|
||||
|
@ -60,8 +60,6 @@ public class AnnotatedJoinColumns {
|
|||
private boolean elementCollection;
|
||||
private String manyToManyOwnerSideEntityName;
|
||||
|
||||
public AnnotatedJoinColumns() {}
|
||||
|
||||
public static AnnotatedJoinColumns buildJoinColumnsOrFormulas(
|
||||
JoinColumnOrFormula[] joinColumnOrFormulas,
|
||||
String mappedBy,
|
||||
|
@ -204,7 +202,13 @@ public class AnnotatedJoinColumns {
|
|||
return columns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColumns(AnnotatedColumn[] columns) {
|
||||
throw new UnsupportedOperationException( "wrong sort of columns" );
|
||||
}
|
||||
|
||||
public void setColumns(AnnotatedJoinColumn[] columns) {
|
||||
super.setColumns( columns );
|
||||
this.columns = columns;
|
||||
if ( columns != null ) {
|
||||
for ( AnnotatedJoinColumn column : columns ) {
|
||||
|
|
|
@ -1118,7 +1118,7 @@ public final class AnnotationBinder {
|
|||
entityBinder,
|
||||
context
|
||||
).extractMetadata();
|
||||
AnnotatedColumn[] columns = columnsBuilder.getColumns();
|
||||
AnnotatedColumns columns = columnsBuilder.getColumns();
|
||||
AnnotatedJoinColumns joinColumns = columnsBuilder.getJoinColumns();
|
||||
|
||||
final PropertyBinder propertyBinder = new PropertyBinder();
|
||||
|
@ -1252,7 +1252,7 @@ public final class AnnotationBinder {
|
|||
MetadataBuildingContext context,
|
||||
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||
XProperty property,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
PropertyBinder propertyBinder) {
|
||||
if (isIdentifierMapper) {
|
||||
throw new AnnotationException(
|
||||
|
@ -1303,7 +1303,7 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private static AnnotatedColumn[] bindBasic(
|
||||
private static AnnotatedColumns bindBasic(
|
||||
PropertyHolder propertyHolder,
|
||||
Nullability nullability,
|
||||
PropertyData inferredData,
|
||||
|
@ -1315,14 +1315,14 @@ public final class AnnotationBinder {
|
|||
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||
XProperty property,
|
||||
ColumnsBuilder columnsBuilder,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
XClass returnedClass,
|
||||
PropertyBinder propertyBinder) {
|
||||
|
||||
// overrides from @MapsId or @IdClass if needed
|
||||
final boolean isComposite;
|
||||
final boolean isOverridden;
|
||||
final AnnotatedColumn[] actualColumns;
|
||||
final AnnotatedColumns actualColumns;
|
||||
if ( propertyBinder.isId() || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
|
||||
// the associated entity could be using an @IdClass making the overridden property a component
|
||||
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||
|
@ -1450,7 +1450,7 @@ public final class AnnotationBinder {
|
|||
Nullability nullability,
|
||||
MetadataBuildingContext context,
|
||||
XProperty property,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
PropertyBinder propertyBinder,
|
||||
boolean isOverridden) {
|
||||
//provide the basic property mapping
|
||||
|
@ -1469,12 +1469,12 @@ public final class AnnotationBinder {
|
|||
//implicit type will check basic types and Serializable classes
|
||||
if ( propertyBinder.isId() || !optional && nullability != Nullability.FORCED_NULL ) {
|
||||
//force columns to not null
|
||||
for ( AnnotatedColumn col : columns ) {
|
||||
if ( propertyBinder.isId() && col.isFormula() ) {
|
||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||
if ( propertyBinder.isId() && column.isFormula() ) {
|
||||
throw new CannotForceNonNullableException( "Identifier property '"
|
||||
+ getPath( propertyHolder, inferrredData ) + "' cannot map to a '@Formula'" );
|
||||
}
|
||||
col.forceNotNull();
|
||||
column.forceNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1499,7 +1499,7 @@ public final class AnnotationBinder {
|
|||
MetadataBuildingContext context,
|
||||
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||
XProperty property,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
XClass returnedClass,
|
||||
PropertyBinder propertyBinder,
|
||||
boolean isOverridden,
|
||||
|
@ -1509,7 +1509,7 @@ public final class AnnotationBinder {
|
|||
final AnnotatedJoinColumns actualColumns;
|
||||
if ( isOverridden ) {
|
||||
// careful: not always a @MapsId property, sometimes it's from an @IdClass
|
||||
PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||
propertyBinder.isId(), propertyHolder, property.getName(), context
|
||||
);
|
||||
referencedEntityName = mapsIdProperty.getClassOrElementName();
|
||||
|
@ -1518,7 +1518,7 @@ public final class AnnotationBinder {
|
|||
joinColumns.setBuildingContext( context );
|
||||
joinColumns.setPropertyHolder( propertyHolder );
|
||||
joinColumns.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns );
|
||||
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns.getColumns() );
|
||||
actualColumns = joinColumns;
|
||||
}
|
||||
else {
|
||||
|
@ -1574,9 +1574,9 @@ public final class AnnotationBinder {
|
|||
);
|
||||
}
|
||||
|
||||
Cascade hibernateCascade = property.getAnnotation( Cascade.class );
|
||||
OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
|
||||
JoinTable assocTable = propertyHolder.getJoinTable(property);
|
||||
final Cascade hibernateCascade = property.getAnnotation( Cascade.class );
|
||||
final OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
|
||||
final JoinTable assocTable = propertyHolder.getJoinTable(property);
|
||||
if ( assocTable != null ) {
|
||||
Join join = propertyHolder.addJoin( assocTable, false );
|
||||
for ( AnnotatedJoinColumn joinColumn : joinColumns.getColumns() ) {
|
||||
|
@ -1600,7 +1600,7 @@ public final class AnnotationBinder {
|
|||
private static void addIndexes(
|
||||
boolean inSecondPass,
|
||||
XProperty property,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
AnnotatedJoinColumns joinColumns) {
|
||||
//process indexes after everything: in second pass, many to one has to be done before indexes
|
||||
final Index index = property.getAnnotation( Index.class );
|
||||
|
@ -1613,7 +1613,7 @@ public final class AnnotationBinder {
|
|||
}
|
||||
else {
|
||||
if ( columns != null ) {
|
||||
for ( AnnotatedColumn column : columns ) {
|
||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||
column.addIndex( index, inSecondPass );
|
||||
}
|
||||
}
|
||||
|
@ -1624,7 +1624,7 @@ public final class AnnotationBinder {
|
|||
private static void addNaturalIds(
|
||||
boolean inSecondPass,
|
||||
XProperty property,
|
||||
AnnotatedColumn[] columns,
|
||||
AnnotatedColumns columns,
|
||||
AnnotatedJoinColumns joinColumns) {
|
||||
// Natural ID columns must reside in one single UniqueKey within the Table.
|
||||
// For now, simply ensure consistent naming.
|
||||
|
@ -1639,7 +1639,7 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
else {
|
||||
for ( AnnotatedColumn column : columns) {
|
||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||
String keyName = "UK_" + Constraint.hashedName( column.getTable().getName() + "_NaturalID" );
|
||||
column.addUniqueKey( keyName, inSecondPass );
|
||||
}
|
||||
|
@ -2254,8 +2254,8 @@ public final class AnnotationBinder {
|
|||
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||
binder.setCascade( cascadeStrategy );
|
||||
Property prop = binder.makeProperty();
|
||||
//composite FK columns are in the same table so its OK
|
||||
propertyHolder.addProperty( prop, columns.getColumns(), inferredData.getDeclaringClass() );
|
||||
//composite FK columns are in the same table, so it's OK
|
||||
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
|
||||
}
|
||||
|
||||
public static HashMap<String, IdentifierGeneratorDefinition> buildGenerators(
|
||||
|
|
|
@ -1049,17 +1049,18 @@ public class BinderHelper {
|
|||
EntityBinder entityBinder,
|
||||
boolean optional,
|
||||
MetadataBuildingContext context) {
|
||||
final XProperty xProperty = inferredData.getProperty();
|
||||
final AnnotatedJoinColumn[] columns = keyColumns.getColumns();
|
||||
final XProperty property = inferredData.getProperty();
|
||||
|
||||
final Any value = new Any( context, columns[0].getTable(), true );
|
||||
final Any value = new Any( context, keyColumns.getTable(), true );
|
||||
value.setLazy( lazy );
|
||||
value.setCascadeDeleteEnabled( cascadeOnDelete );
|
||||
|
||||
final BasicValueBinder discriminatorValueBinder =
|
||||
new BasicValueBinder( BasicValueBinder.Kind.ANY_DISCRIMINATOR, context );
|
||||
|
||||
final AnnotatedColumn[] discriminatorColumns = buildColumnOrFormulaFromAnnotation(
|
||||
// TODO: if there can be only one discriminator column,
|
||||
// why are we making a whole array of them??
|
||||
final AnnotatedColumns discriminatorColumns = buildColumnOrFormulaFromAnnotation(
|
||||
discriminatorColumn,
|
||||
discriminatorFormula,
|
||||
null,
|
||||
|
@ -1069,17 +1070,20 @@ public class BinderHelper {
|
|||
entityBinder.getSecondaryTables(),
|
||||
context
|
||||
);
|
||||
assert discriminatorColumns.length == 1;
|
||||
discriminatorColumns[0].setTable( value.getTable() );
|
||||
assert discriminatorColumns.getColumns().length == 1;
|
||||
|
||||
discriminatorColumns.setTable( value.getTable() );
|
||||
discriminatorValueBinder.setColumns( discriminatorColumns );
|
||||
|
||||
discriminatorValueBinder.setReturnedClassName( inferredData.getTypeName() );
|
||||
discriminatorValueBinder.setType( xProperty, xProperty.getType(), null, null );
|
||||
discriminatorValueBinder.setType( property, property.getType(), null, null );
|
||||
|
||||
final BasicValue discriminatorDescriptor = discriminatorValueBinder.make();
|
||||
value.setDiscriminator( discriminatorDescriptor );
|
||||
discriminatorValueBinder.fillSimpleValue();
|
||||
discriminatorColumns[0].linkWithValue( discriminatorDescriptor );
|
||||
// TODO: this is nasty
|
||||
final AnnotatedColumn firstDiscriminatorColumn = discriminatorColumns.getColumns()[0];
|
||||
firstDiscriminatorColumn.linkWithValue( discriminatorDescriptor );
|
||||
|
||||
final JavaType<?> discriminatorJavaType = discriminatorDescriptor
|
||||
.resolve()
|
||||
|
@ -1095,26 +1099,23 @@ public class BinderHelper {
|
|||
);
|
||||
value.setDiscriminatorValueMappings( discriminatorValueMappings );
|
||||
|
||||
BasicValueBinder keyValueBinder = new BasicValueBinder( BasicValueBinder.Kind.ANY_KEY, context );
|
||||
final BasicValueBinder keyValueBinder = new BasicValueBinder( BasicValueBinder.Kind.ANY_KEY, context );
|
||||
final AnnotatedJoinColumn[] columns = keyColumns.getColumns();
|
||||
assert columns.length == 1;
|
||||
columns[0].setTable( value.getTable() );
|
||||
keyValueBinder.setColumns(columns);
|
||||
|
||||
keyColumns.setTable( value.getTable() );
|
||||
keyValueBinder.setColumns( keyColumns );
|
||||
if ( !optional ) {
|
||||
for ( AnnotatedJoinColumn column : columns) {
|
||||
for ( AnnotatedJoinColumn column : columns ) {
|
||||
column.setNullable( false );
|
||||
}
|
||||
}
|
||||
keyValueBinder.setType( xProperty, xProperty.getType(), null, null );
|
||||
keyValueBinder.setType( property, property.getType(), null, null );
|
||||
final BasicValue keyDescriptor = keyValueBinder.make();
|
||||
value.setKey( keyDescriptor );
|
||||
keyValueBinder.fillSimpleValue();
|
||||
AnnotatedColumn.checkPropertyConsistency(
|
||||
columns,
|
||||
propertyHolder.getEntityName() + "." + inferredData.getPropertyName()
|
||||
);
|
||||
final String path = qualify( propertyHolder.getEntityName(), inferredData.getPropertyName() );
|
||||
AnnotatedColumn.checkPropertyConsistency( columns, path );
|
||||
columns[0].linkWithValue( keyDescriptor );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ 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;
|
||||
|
@ -181,12 +182,23 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
|
|||
return persistentClass.getEntityName();
|
||||
}
|
||||
|
||||
public void addProperty(Property prop, AnnotatedColumn[] columns, XClass declaringClass) {
|
||||
public void addProperty(Property prop, AnnotatedColumns columns, XClass declaringClass) {
|
||||
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
|
||||
if ( columns != null && columns[0].isSecondary() ) {
|
||||
//TODO move the getJoin() code here?
|
||||
final Join join = columns[0].getJoin();
|
||||
addPropertyToJoin( prop, declaringClass, join );
|
||||
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() );
|
||||
}
|
||||
else {
|
||||
addProperty( prop, declaringClass );
|
||||
}
|
||||
}
|
||||
else {
|
||||
addProperty( prop, declaringClass );
|
||||
|
|
|
@ -309,7 +309,7 @@ public class CollectionPropertyHolder extends AbstractPropertyHolder {
|
|||
return collection.getOwner().getEntityName();
|
||||
}
|
||||
|
||||
public void addProperty(Property prop, AnnotatedColumn[] columns, XClass declaringClass) {
|
||||
public void addProperty(Property prop, AnnotatedColumns columns, XClass declaringClass) {
|
||||
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
|
||||
throw new AssertionFailure( "addProperty to a join table of a collection: does it make sense?" );
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class ColumnsBuilder {
|
|||
private final PropertyData inferredData;
|
||||
private final EntityBinder entityBinder;
|
||||
private final MetadataBuildingContext buildingContext;
|
||||
private AnnotatedColumn[] columns;
|
||||
private AnnotatedColumns columns;
|
||||
private AnnotatedJoinColumns joinColumns;
|
||||
|
||||
public ColumnsBuilder(
|
||||
|
@ -70,7 +70,7 @@ class ColumnsBuilder {
|
|||
this.buildingContext = buildingContext;
|
||||
}
|
||||
|
||||
public AnnotatedColumn[] getColumns() {
|
||||
public AnnotatedColumns getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
@ -158,8 +158,8 @@ class ColumnsBuilder {
|
|||
|
||||
if ( nullability == Nullability.FORCED_NOT_NULL ) {
|
||||
//force columns to not null
|
||||
for (AnnotatedColumn col : columns ) {
|
||||
col.forceNotNull();
|
||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||
column.forceNotNull();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -291,13 +291,9 @@ class ColumnsBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
AnnotatedColumn[] overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
|
||||
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||
isId,
|
||||
propertyHolder,
|
||||
property.getName(),
|
||||
buildingContext
|
||||
);
|
||||
AnnotatedColumns overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
|
||||
final PropertyData overridingProperty =
|
||||
getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder, property.getName(), buildingContext );
|
||||
return overridingProperty != null ? buildExplicitOrDefaultJoinColumn( overridingProperty ) : columns;
|
||||
}
|
||||
|
||||
|
@ -305,10 +301,10 @@ class ColumnsBuilder {
|
|||
* 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 AnnotatedColumn[] buildExplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
|
||||
private AnnotatedColumns buildExplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
|
||||
final AnnotatedJoinColumns columns = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
|
||||
return columns == null
|
||||
? buildDefaultJoinColumnsForToOne( overridingProperty.getProperty(), overridingProperty ).getColumns()
|
||||
: columns.getColumns();
|
||||
? buildDefaultJoinColumnsForToOne( overridingProperty.getProperty(), overridingProperty )
|
||||
: columns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,12 +251,12 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|
|||
@Override
|
||||
protected AttributeConversionInfo locateAttributeConversionInfo(String path) {
|
||||
final String embeddedPath = StringHelper.qualifyConditionally( embeddedAttributeName, path );
|
||||
AttributeConversionInfo fromParent = parent.locateAttributeConversionInfo( embeddedPath );
|
||||
final AttributeConversionInfo fromParent = parent.locateAttributeConversionInfo( embeddedPath );
|
||||
if ( fromParent != null ) {
|
||||
return fromParent;
|
||||
}
|
||||
|
||||
AttributeConversionInfo fromEmbedded = attributeConversionInfoMap.get( embeddedPath );
|
||||
final AttributeConversionInfo fromEmbedded = attributeConversionInfoMap.get( embeddedPath );
|
||||
if ( fromEmbedded != null ) {
|
||||
return fromEmbedded;
|
||||
}
|
||||
|
@ -268,13 +268,13 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|
|||
return component.getComponentClassName();
|
||||
}
|
||||
|
||||
public void addProperty(Property prop, AnnotatedColumn[] columns, XClass declaringClass) {
|
||||
public void addProperty(Property property, AnnotatedColumns columns, XClass declaringClass) {
|
||||
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
|
||||
// Check table matches between the component and the columns
|
||||
// if not, change the component table if no properties are set
|
||||
// if a property is set already the core cannot support that
|
||||
if (columns != null) {
|
||||
Table table = columns[0].getTable();
|
||||
if ( columns != null ) {
|
||||
final Table table = columns.getTable();
|
||||
if ( !table.equals( component.getTable() ) ) {
|
||||
if ( component.getPropertySpan() == 0 ) {
|
||||
component.setTable( table );
|
||||
|
@ -288,12 +288,11 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
|
|||
}
|
||||
}
|
||||
}
|
||||
addProperty( prop, declaringClass );
|
||||
addProperty( property, declaringClass );
|
||||
}
|
||||
|
||||
public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) {
|
||||
return parent.addJoin( joinTableAnn, noDelayInPkColumnCreation );
|
||||
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
|
|
|
@ -59,16 +59,15 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
@Override
|
||||
public void doSecondPass(Map<String, PersistentClass> persistentClasses) throws MappingException {
|
||||
if ( columns != null ) {
|
||||
for ( String column1 : columns ) {
|
||||
addConstraintToColumn( column1 );
|
||||
for ( String columnName : columns ) {
|
||||
addConstraintToColumn( columnName );
|
||||
}
|
||||
}
|
||||
if ( column != null ) {
|
||||
this.table = column.getTable();
|
||||
table = column.getTable();
|
||||
|
||||
final PropertyHolder propertyHolder = column.getPropertyHolder();
|
||||
|
||||
String entityName = ( propertyHolder.isComponent() ) ?
|
||||
final String entityName = ( propertyHolder.isComponent() ) ?
|
||||
propertyHolder.getPersistentClass().getEntityName() :
|
||||
propertyHolder.getEntityName();
|
||||
|
||||
|
@ -77,8 +76,7 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
|
||||
if ( property.getValue() instanceof Component ) {
|
||||
final Component component = (Component) property.getValue();
|
||||
|
||||
List<Column> columns = new ArrayList<>();
|
||||
final List<Column> columns = new ArrayList<>();
|
||||
for ( Selectable selectable: component.getSelectables() ) {
|
||||
if ( selectable instanceof Column ) {
|
||||
columns.add( (Column) selectable );
|
||||
|
@ -97,9 +95,7 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
|
||||
private void addConstraintToColumn(final String columnName ) {
|
||||
Column column = table.getColumn(
|
||||
new Column(
|
||||
buildingContext.getMetadataCollector().getPhysicalColumnName( table, columnName )
|
||||
)
|
||||
new Column( buildingContext.getMetadataCollector().getPhysicalColumnName( table, columnName ) )
|
||||
);
|
||||
if ( column == null ) {
|
||||
throw new AnnotationException(
|
||||
|
@ -117,13 +113,13 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
|
||||
private void addConstraintToColumns(List<Column> columns) {
|
||||
if ( unique ) {
|
||||
UniqueKey uniqueKey = table.getOrCreateUniqueKey( indexName );
|
||||
final UniqueKey uniqueKey = table.getOrCreateUniqueKey( indexName );
|
||||
for ( Column column : columns ) {
|
||||
uniqueKey.addColumn( column );
|
||||
}
|
||||
}
|
||||
else {
|
||||
Index index = table.getOrCreateIndex( indexName );
|
||||
final Index index = table.getOrCreateIndex( indexName );
|
||||
for ( Column column : columns ) {
|
||||
index.addColumn( column );
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public interface PropertyHolder {
|
|||
|
||||
void addProperty(Property prop, XClass declaringClass);
|
||||
|
||||
void addProperty(Property prop, AnnotatedColumn[] columns, XClass declaringClass);
|
||||
void addProperty(Property prop, AnnotatedColumns columns, XClass declaringClass);
|
||||
|
||||
KeyValue getIdentifier();
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ public class ToOneBinder {
|
|||
MetadataBuildingContext context) {
|
||||
// All FK columns should be in the same table
|
||||
final org.hibernate.mapping.ManyToOne value =
|
||||
new org.hibernate.mapping.ManyToOne( context, joinColumns.getColumns()[0].getTable() );
|
||||
new org.hibernate.mapping.ManyToOne( context, joinColumns.getTable() );
|
||||
if ( unique ) {
|
||||
// This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne
|
||||
value.markAsLogicalOneToOne();
|
||||
|
@ -269,7 +269,7 @@ public class ToOneBinder {
|
|||
propertyBinder.setInsertable( firstColumn.isInsertable() );
|
||||
propertyBinder.setUpdatable( firstColumn.isUpdatable() );
|
||||
}
|
||||
propertyBinder.setColumns( columns.getColumns() );
|
||||
propertyBinder.setColumns( columns );
|
||||
propertyBinder.setAccessType( inferredData.getDefaultAccess() );
|
||||
propertyBinder.setCascade( cascadeStrategy );
|
||||
propertyBinder.setProperty( property );
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.hibernate.boot.spi.InFlightMetadataCollector;
|
|||
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;
|
||||
|
@ -153,7 +154,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
private TimeZoneStorageType timeZoneStorageType;
|
||||
|
||||
private Table table;
|
||||
private AnnotatedColumn[] columns;
|
||||
private AnnotatedColumns columns;
|
||||
|
||||
private BasicValue basicValue;
|
||||
|
||||
|
@ -274,7 +275,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
this.table = table;
|
||||
}
|
||||
|
||||
public void setColumns(AnnotatedColumn[] columns) {
|
||||
public void setColumns(AnnotatedColumns columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1071,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
}
|
||||
|
||||
private void validate() {
|
||||
AnnotatedColumn.checkPropertyConsistency( columns, propertyName );
|
||||
AnnotatedColumn.checkPropertyConsistency( columns.getColumns(), propertyName );
|
||||
}
|
||||
|
||||
public BasicValue make() {
|
||||
|
@ -1083,7 +1084,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
LOG.debugf( "building BasicValue for %s", propertyName );
|
||||
|
||||
if ( table == null ) {
|
||||
table = columns[0].getTable();
|
||||
table = columns.getTable();
|
||||
}
|
||||
|
||||
basicValue = new BasicValue( buildingContext, table );
|
||||
|
@ -1125,18 +1126,19 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
|||
|
||||
public void linkWithValue() {
|
||||
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
|
||||
if ( !collector.isInSecondPass() && columns[0].isNameDeferred() && referencedEntityName != null ) {
|
||||
final AnnotatedColumn firstColumn = columns.getColumns()[0];
|
||||
if ( !collector.isInSecondPass() && firstColumn.isNameDeferred() && referencedEntityName != null ) {
|
||||
final AnnotatedJoinColumns joinColumns = new AnnotatedJoinColumns();
|
||||
joinColumns.setBuildingContext( buildingContext );
|
||||
joinColumns.setPropertyHolder( columns[0].getPropertyHolder() );
|
||||
joinColumns.setPropertyName( columns[0].getPropertyName() );
|
||||
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns );
|
||||
joinColumns.setPropertyHolder( firstColumn.getPropertyHolder() );
|
||||
joinColumns.setPropertyName( firstColumn.getPropertyName() );
|
||||
joinColumns.setColumns( (AnnotatedJoinColumn[]) columns.getColumns() );
|
||||
collector.addSecondPass(
|
||||
new PkDrivenByDefaultMapsIdSecondPass( referencedEntityName, joinColumns, basicValue )
|
||||
);
|
||||
}
|
||||
else {
|
||||
for ( AnnotatedColumn column : columns ) {
|
||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||
column.linkWithValue( basicValue );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
|
|||
import org.hibernate.cfg.AccessType;
|
||||
import org.hibernate.cfg.AnnotatedClassType;
|
||||
import org.hibernate.cfg.AnnotatedColumn;
|
||||
import org.hibernate.cfg.AnnotatedColumns;
|
||||
import org.hibernate.cfg.AnnotatedJoinColumn;
|
||||
import org.hibernate.cfg.AnnotatedJoinColumns;
|
||||
import org.hibernate.cfg.AnnotationBinder;
|
||||
|
@ -173,6 +174,7 @@ 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.
|
||||
|
@ -216,12 +218,12 @@ public abstract class CollectionBinder {
|
|||
protected AnnotatedJoinColumns foreignJoinColumns;
|
||||
private AnnotatedJoinColumns joinColumns;
|
||||
private boolean isExplicitAssociationTable;
|
||||
private AnnotatedColumn[] elementColumns;
|
||||
private AnnotatedColumns elementColumns;
|
||||
protected boolean isEmbedded;
|
||||
protected XProperty property;
|
||||
protected NotFoundAction notFoundAction;
|
||||
private TableBinder tableBinder;
|
||||
protected AnnotatedColumn[] mapKeyColumns;
|
||||
protected AnnotatedColumns mapKeyColumns;
|
||||
protected AnnotatedJoinColumns mapKeyManyToManyColumns;
|
||||
protected Map<String, IdentifierGeneratorDefinition> localGenerators;
|
||||
protected Map<XClass, InheritanceState> inheritanceStatePerClass;
|
||||
|
@ -321,7 +323,7 @@ public abstract class CollectionBinder {
|
|||
? inferredData
|
||||
: new WrappedInferredData( inferredData, "element" );
|
||||
final Comment comment = property.getAnnotation( Comment.class );
|
||||
final AnnotatedColumn[] elementColumns = elementColumns(
|
||||
final AnnotatedColumns elementColumns = elementColumns(
|
||||
propertyHolder,
|
||||
nullability,
|
||||
entityBinder,
|
||||
|
@ -419,6 +421,7 @@ public abstract class CollectionBinder {
|
|||
if ( oneToManyAnn != null ) {
|
||||
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
|
||||
if ( column.isSecondary() ) {
|
||||
//TODO: fix the error message
|
||||
throw new NotYetImplementedException( "Collections having FK in secondary table" );
|
||||
}
|
||||
}
|
||||
|
@ -434,6 +437,7 @@ public abstract class CollectionBinder {
|
|||
else if ( elementCollectionAnn != null ) {
|
||||
for ( AnnotatedJoinColumn column : joinColumns.getColumns() ) {
|
||||
if ( column.isSecondary() ) {
|
||||
//TODO: fix the error message
|
||||
throw new NotYetImplementedException( "Collections having FK in secondary table" );
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +491,7 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private static AnnotatedColumn[] elementColumns(
|
||||
private static AnnotatedColumns elementColumns(
|
||||
PropertyHolder propertyHolder,
|
||||
Nullability nullability,
|
||||
EntityBinder entityBinder,
|
||||
|
@ -553,7 +557,7 @@ public abstract class CollectionBinder {
|
|||
? new jakarta.persistence.Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) }
|
||||
: null;
|
||||
|
||||
final AnnotatedColumn[] mapColumns = buildColumnsFromAnnotations(
|
||||
final AnnotatedColumns mapColumns = buildColumnsFromAnnotations(
|
||||
keyColumns,
|
||||
comment,
|
||||
Nullability.FORCED_NOT_NULL,
|
||||
|
@ -1544,9 +1548,8 @@ public abstract class CollectionBinder {
|
|||
foreignJoinColumns.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
|
||||
for ( AnnotatedJoinColumn column : foreignJoinColumns.getColumns() ) {
|
||||
column.setJoins( joins );
|
||||
//TODO: this is lame, should get the table from foreignJoinColumns
|
||||
collection.setCollectionTable( column.getTable() );
|
||||
}
|
||||
collection.setCollectionTable( foreignJoinColumns.getTable() );
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Mapping collection: %s -> %s", collection.getRole(), collection.getCollectionTable().getName() );
|
||||
}
|
||||
|
@ -1555,7 +1558,7 @@ public abstract class CollectionBinder {
|
|||
handleWhere( false );
|
||||
|
||||
final PersistentClass targetEntity = persistentClasses.get( getElementType().getName() );
|
||||
bindCollectionSecondPass( targetEntity, foreignJoinColumns, cascadeDeleteEnabled, buildingContext );
|
||||
bindCollectionSecondPass( targetEntity, foreignJoinColumns, cascadeDeleteEnabled );
|
||||
|
||||
if ( !collection.isInverse() && !collection.getKey().isNullable() ) {
|
||||
createOneToManyBackref( oneToMany );
|
||||
|
@ -1838,12 +1841,11 @@ public abstract class CollectionBinder {
|
|||
boolean cascadeDeleteEnabled,
|
||||
boolean noConstraintByDefault,
|
||||
XProperty property,
|
||||
PropertyHolder propertyHolder,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
PropertyHolder propertyHolder) {
|
||||
|
||||
// give a chance to override the referenced property name
|
||||
// has to do that here because the referencedProperty creation happens in a FKSecondPass for ManyToOne yuk!
|
||||
overrideReferencedPropertyName( collection, joinColumns, buildingContext );
|
||||
overrideReferencedPropertyName( collection, joinColumns );
|
||||
|
||||
final String referencedPropertyName = collection.getReferencedPropertyName();
|
||||
//binding key reference using column
|
||||
|
@ -1955,15 +1957,12 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private void overrideReferencedPropertyName(
|
||||
Collection collection,
|
||||
AnnotatedJoinColumns joinColumns,
|
||||
MetadataBuildingContext context) {
|
||||
private void overrideReferencedPropertyName(Collection collection, AnnotatedJoinColumns joinColumns) {
|
||||
if ( hasMappedBy() && joinColumns.getColumns().length > 0 ) {
|
||||
final String entityName = joinColumns.getManyToManyOwnerSideEntityName() != null
|
||||
? "inverse__" + joinColumns.getManyToManyOwnerSideEntityName()
|
||||
: joinColumns.getPropertyHolder().getEntityName();
|
||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||
final InFlightMetadataCollector collector = buildingContext.getMetadataCollector();
|
||||
final String referencedProperty = collector.getPropertyReferencedAssociation( entityName, mappedBy );
|
||||
if ( referencedProperty != null ) {
|
||||
collection.setReferencedPropertyName( referencedProperty );
|
||||
|
@ -2021,7 +2020,7 @@ public abstract class CollectionBinder {
|
|||
bindFilters( isCollectionOfEntities );
|
||||
handleWhere( isCollectionOfEntities );
|
||||
|
||||
bindCollectionSecondPass( targetEntity, joinColumns, cascadeDeleteEnabled, buildingContext );
|
||||
bindCollectionSecondPass( targetEntity, joinColumns, cascadeDeleteEnabled );
|
||||
|
||||
if ( isCollectionOfEntities ) {
|
||||
final ManyToOne element = handleCollectionOfEntities(
|
||||
|
@ -2033,7 +2032,7 @@ public abstract class CollectionBinder {
|
|||
targetEntity,
|
||||
hqlOrderBy
|
||||
);
|
||||
bindManyToManyInverseForeignKey( targetEntity, inverseJoinColumns, element, oneToMany, buildingContext );
|
||||
bindManyToManyInverseForeignKey( targetEntity, inverseJoinColumns, element, oneToMany );
|
||||
}
|
||||
else if ( isManyToAny ) {
|
||||
handleManyToAny(
|
||||
|
@ -2052,7 +2051,6 @@ public abstract class CollectionBinder {
|
|||
elementType,
|
||||
property,
|
||||
propertyHolder,
|
||||
buildingContext,
|
||||
hqlOrderBy
|
||||
);
|
||||
}
|
||||
|
@ -2062,12 +2060,11 @@ public abstract class CollectionBinder {
|
|||
|
||||
private void handleElementCollection(
|
||||
Collection collection,
|
||||
AnnotatedColumn[] elementColumns,
|
||||
AnnotatedColumns elementColumns,
|
||||
boolean isEmbedded,
|
||||
XClass elementType,
|
||||
XProperty property,
|
||||
PropertyHolder parentPropertyHolder,
|
||||
MetadataBuildingContext buildingContext,
|
||||
String hqlOrderBy) {
|
||||
final XClass elementClass;
|
||||
final AnnotatedClassType classType;
|
||||
|
@ -2151,7 +2148,7 @@ public abstract class CollectionBinder {
|
|||
false,
|
||||
false,
|
||||
true,
|
||||
resolveCustomInstantiator(property, elementClass, buildingContext),
|
||||
resolveCustomInstantiator( property, elementClass, buildingContext ),
|
||||
compositeUserType,
|
||||
buildingContext,
|
||||
inheritanceStatePerClass
|
||||
|
@ -2170,26 +2167,16 @@ public abstract class CollectionBinder {
|
|||
holder.prepare( property );
|
||||
|
||||
final BasicValueBinder elementBinder =
|
||||
new BasicValueBinder( BasicValueBinder.Kind.COLLECTION_ELEMENT, buildingContext);
|
||||
new BasicValueBinder( BasicValueBinder.Kind.COLLECTION_ELEMENT, buildingContext );
|
||||
elementBinder.setReturnedClassName( elementType.getName() );
|
||||
if ( elementColumns == null || elementColumns.length == 0 ) {
|
||||
elementColumns = new AnnotatedColumn[1];
|
||||
AnnotatedColumn column = new AnnotatedColumn();
|
||||
column.setImplicit( false );
|
||||
//not following the spec but more clean
|
||||
column.setNullable( true );
|
||||
column.setLogicalColumnName( Collection.DEFAULT_ELEMENT_COLUMN_NAME );
|
||||
//TODO create an EMPTY_JOINS collection
|
||||
column.setJoins( new HashMap<>() );
|
||||
column.setBuildingContext(buildingContext);
|
||||
column.bind();
|
||||
elementColumns[0] = column;
|
||||
}
|
||||
//override the table
|
||||
for (AnnotatedColumn column : elementColumns) {
|
||||
column.setTable( collection.getCollectionTable() );
|
||||
}
|
||||
elementBinder.setColumns(elementColumns);
|
||||
final AnnotatedColumns actualColumns = createElementColumnsIfNecessary(
|
||||
collection,
|
||||
elementColumns,
|
||||
Collection.DEFAULT_ELEMENT_COLUMN_NAME,
|
||||
null,
|
||||
buildingContext
|
||||
);
|
||||
elementBinder.setColumns( actualColumns );
|
||||
elementBinder.setType(
|
||||
property,
|
||||
elementClass,
|
||||
|
@ -2206,6 +2193,34 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
}
|
||||
|
||||
static AnnotatedColumns createElementColumnsIfNecessary(
|
||||
Collection collection,
|
||||
AnnotatedColumns elementColumns,
|
||||
String defaultName,
|
||||
Long defaultLength,
|
||||
MetadataBuildingContext context) {
|
||||
if ( elementColumns == null || isEmpty( elementColumns.getColumns() ) ) {
|
||||
final AnnotatedColumn column = new AnnotatedColumn();
|
||||
column.setLogicalColumnName( defaultName );
|
||||
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.bind();
|
||||
final AnnotatedColumns result = new AnnotatedColumns();
|
||||
result.setColumns( new AnnotatedColumn[] { column } );
|
||||
elementColumns = result;
|
||||
}
|
||||
//override the table
|
||||
elementColumns.setTable( collection.getCollectionTable() );
|
||||
return elementColumns;
|
||||
}
|
||||
|
||||
private ManyToOne handleCollectionOfEntities(
|
||||
Collection collection,
|
||||
XClass elementType,
|
||||
|
@ -2214,7 +2229,7 @@ public abstract class CollectionBinder {
|
|||
MetadataBuildingContext buildingContext,
|
||||
PersistentClass collectionEntity,
|
||||
String hqlOrderBy) {
|
||||
ManyToOne element = new ManyToOne( buildingContext, collection.getCollectionTable() );
|
||||
final ManyToOne element = new ManyToOne( buildingContext, collection.getCollectionTable() );
|
||||
collection.setElement( element );
|
||||
element.setReferencedEntityName( elementType.getName() );
|
||||
//element.setFetchMode( fetchMode );
|
||||
|
@ -2273,16 +2288,14 @@ public abstract class CollectionBinder {
|
|||
buildingContext.getBootstrapContext().getReflectionManager()
|
||||
);
|
||||
|
||||
XProperty prop = inferredData.getProperty();
|
||||
final XProperty prop = inferredData.getProperty();
|
||||
final jakarta.persistence.Column discriminatorColumnAnn = prop.getAnnotation( jakarta.persistence.Column.class );
|
||||
final Formula discriminatorFormulaAnn = getOverridableAnnotation( prop, Formula.class, buildingContext);
|
||||
|
||||
//override the table
|
||||
for ( AnnotatedColumn column : inverseJoinColumns.getColumns() ) {
|
||||
column.setTable( collection.getCollectionTable() );
|
||||
}
|
||||
inverseJoinColumns.setTable( collection.getCollectionTable() );
|
||||
|
||||
ManyToAny anyAnn = property.getAnnotation( ManyToAny.class );
|
||||
final ManyToAny anyAnn = property.getAnnotation( ManyToAny.class );
|
||||
final Any any = buildAnyValue(
|
||||
discriminatorColumnAnn,
|
||||
discriminatorFormulaAnn,
|
||||
|
@ -2486,8 +2499,7 @@ public abstract class CollectionBinder {
|
|||
private void bindCollectionSecondPass(
|
||||
PersistentClass targetEntity,
|
||||
AnnotatedJoinColumns joinColumns,
|
||||
boolean cascadeDeleteEnabled,
|
||||
MetadataBuildingContext context) {
|
||||
boolean cascadeDeleteEnabled) {
|
||||
|
||||
if ( !hasMappedBy() ) {
|
||||
createSyntheticPropertyReference(
|
||||
|
@ -2497,7 +2509,7 @@ public abstract class CollectionBinder {
|
|||
collection,
|
||||
propertyName,
|
||||
false,
|
||||
context
|
||||
buildingContext
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2505,10 +2517,9 @@ public abstract class CollectionBinder {
|
|||
collection,
|
||||
joinColumns,
|
||||
cascadeDeleteEnabled,
|
||||
context.getBuildingOptions().isNoConstraintByDefault(),
|
||||
buildingContext.getBuildingOptions().isNoConstraintByDefault(),
|
||||
property,
|
||||
propertyHolder,
|
||||
context
|
||||
propertyHolder
|
||||
);
|
||||
|
||||
if ( property.isAnnotationPresent( ElementCollection.class ) ) {
|
||||
|
@ -2521,7 +2532,7 @@ public abstract class CollectionBinder {
|
|||
joinColumns,
|
||||
key,
|
||||
false,
|
||||
context
|
||||
buildingContext
|
||||
);
|
||||
key.sortProperties();
|
||||
}
|
||||
|
@ -2545,8 +2556,7 @@ public abstract class CollectionBinder {
|
|||
PersistentClass targetEntity,
|
||||
AnnotatedJoinColumns joinColumns,
|
||||
SimpleValue value,
|
||||
boolean unique,
|
||||
MetadataBuildingContext context) {
|
||||
boolean unique) {
|
||||
if ( hasMappedBy() ) {
|
||||
final Property property = targetEntity.getRecursiveProperty( mappedBy );
|
||||
final List<Selectable> mappedByColumns = mappedByColumns( targetEntity, property );
|
||||
|
@ -2554,12 +2564,12 @@ public abstract class CollectionBinder {
|
|||
for ( Selectable selectable: mappedByColumns ) {
|
||||
firstColumn.linkValueUsingAColumnCopy( (Column) selectable, value );
|
||||
}
|
||||
final String referencedPropertyName = context.getMetadataCollector()
|
||||
final String referencedPropertyName = buildingContext.getMetadataCollector()
|
||||
.getPropertyReferencedAssociation( targetEntity.getEntityName(), mappedBy );
|
||||
if ( referencedPropertyName != null ) {
|
||||
//TODO always a many to one?
|
||||
( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName );
|
||||
context.getMetadataCollector()
|
||||
buildingContext.getMetadataCollector()
|
||||
.addUniquePropertyReference( targetEntity.getEntityName(), referencedPropertyName );
|
||||
}
|
||||
( (ManyToOne) value ).setReferenceToPrimaryKey( referencedPropertyName == null );
|
||||
|
@ -2573,7 +2583,7 @@ public abstract class CollectionBinder {
|
|||
value,
|
||||
propertyName,
|
||||
true,
|
||||
context
|
||||
buildingContext
|
||||
);
|
||||
if ( notFoundAction == NotFoundAction.IGNORE ) {
|
||||
value.disableForeignKey();
|
||||
|
@ -2584,7 +2594,7 @@ public abstract class CollectionBinder {
|
|||
joinColumns,
|
||||
value,
|
||||
unique,
|
||||
context
|
||||
buildingContext
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2617,7 +2627,7 @@ public abstract class CollectionBinder {
|
|||
this.isExplicitAssociationTable = explicitAssocTable;
|
||||
}
|
||||
|
||||
public void setElementColumns(AnnotatedColumn[] elementColumns) {
|
||||
public void setElementColumns(AnnotatedColumns elementColumns) {
|
||||
this.elementColumns = elementColumns;
|
||||
}
|
||||
|
||||
|
@ -2637,7 +2647,7 @@ public abstract class CollectionBinder {
|
|||
this.notFoundAction = notFoundAction;
|
||||
}
|
||||
|
||||
public void setMapKeyColumns(AnnotatedColumn[] mapKeyColumns) {
|
||||
public void setMapKeyColumns(AnnotatedColumns mapKeyColumns) {
|
||||
this.mapKeyColumns = mapKeyColumns;
|
||||
}
|
||||
|
||||
|
|
|
@ -789,7 +789,7 @@ public class EntityBinder {
|
|||
}
|
||||
discriminatorColumn.setJoins( secondaryTables );
|
||||
discriminatorColumn.setPropertyHolder( propertyHolder );
|
||||
BasicValue discriminatorColumnBinding = new BasicValue( context, rootClass.getTable() );
|
||||
final BasicValue discriminatorColumnBinding = new BasicValue( context, rootClass.getTable() );
|
||||
rootClass.setDiscriminator( discriminatorColumnBinding );
|
||||
discriminatorColumn.linkWithValue( discriminatorColumnBinding );
|
||||
discriminatorColumnBinding.setTypeName( discriminatorColumn.getDiscriminatorTypeName() );
|
||||
|
|
|
@ -12,12 +12,9 @@ import java.util.function.Supplier;
|
|||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.CollectionId;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.AnnotatedColumn;
|
||||
import org.hibernate.cfg.AnnotatedJoinColumn;
|
||||
import org.hibernate.cfg.AnnotatedColumns;
|
||||
import org.hibernate.cfg.IdGeneratorResolverSecondPass;
|
||||
import org.hibernate.cfg.PropertyData;
|
||||
import org.hibernate.cfg.PropertyInferredData;
|
||||
|
@ -71,7 +68,7 @@ public class IdBagBinder extends BagBinder {
|
|||
"id"
|
||||
);
|
||||
|
||||
final AnnotatedColumn[] idColumns = AnnotatedColumn.buildColumnsFromAnnotations(
|
||||
final AnnotatedColumns idColumns = AnnotatedColumn.buildColumnsFromAnnotations(
|
||||
new Column[] { collectionIdAnn.column() },
|
||||
null,
|
||||
Nullability.FORCED_NOT_NULL,
|
||||
|
@ -82,7 +79,7 @@ public class IdBagBinder extends BagBinder {
|
|||
);
|
||||
|
||||
//we need to make sure all id columns must be not-null.
|
||||
for ( AnnotatedColumn idColumn:idColumns ) {
|
||||
for ( AnnotatedColumn idColumn : idColumns.getColumns() ) {
|
||||
idColumn.setNullable( false );
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,9 @@ import java.util.function.Supplier;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.OrderBy;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.CollectionSecondPass;
|
||||
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;
|
||||
import org.hibernate.cfg.SecondPass;
|
||||
|
@ -87,7 +88,9 @@ public class ListBinder extends CollectionBinder {
|
|||
}
|
||||
indexColumn.setPropertyHolder( valueHolder );
|
||||
final BasicValueBinder valueBinder = new BasicValueBinder( BasicValueBinder.Kind.LIST_INDEX, buildingContext );
|
||||
valueBinder.setColumns( new AnnotatedColumn[] { indexColumn } );
|
||||
final AnnotatedColumns result = new AnnotatedColumns();
|
||||
result.setColumns( new AnnotatedColumn[] { indexColumn } );
|
||||
valueBinder.setColumns(result);
|
||||
valueBinder.setReturnedClassName( Integer.class.getName() );
|
||||
valueBinder.setType( property, getElementType(), null, null );
|
||||
// valueBinder.setExplicitType( "integer" );
|
||||
|
@ -95,7 +98,13 @@ public class ListBinder extends CollectionBinder {
|
|||
indexColumn.linkWithValue( indexValue );
|
||||
listValueMapping.setIndex( indexValue );
|
||||
listValueMapping.setBaseIndex( indexColumn.getBase() );
|
||||
if ( listValueMapping.isOneToMany() && !listValueMapping.getKey().isNullable() && !listValueMapping.isInverse() ) {
|
||||
createBackref( listValueMapping );
|
||||
}
|
||||
|
||||
private void createBackref(List listValueMapping) {
|
||||
if ( listValueMapping.isOneToMany()
|
||||
&& !listValueMapping.getKey().isNullable()
|
||||
&& !listValueMapping.isInverse() ) {
|
||||
final String entityName = ( (OneToMany) listValueMapping.getElement() ).getReferencedEntityName();
|
||||
final PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
|
||||
final IndexBackref backref = new IndexBackref();
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -22,11 +21,11 @@ import org.hibernate.boot.spi.BootstrapContext;
|
|||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.AccessType;
|
||||
import org.hibernate.cfg.AnnotatedClassType;
|
||||
import org.hibernate.cfg.AnnotatedColumns;
|
||||
import org.hibernate.cfg.AnnotatedJoinColumns;
|
||||
import org.hibernate.cfg.AnnotationBinder;
|
||||
import org.hibernate.cfg.CollectionPropertyHolder;
|
||||
import org.hibernate.cfg.CollectionSecondPass;
|
||||
import org.hibernate.cfg.AnnotatedColumn;
|
||||
import org.hibernate.cfg.AnnotatedJoinColumn;
|
||||
import org.hibernate.cfg.InheritanceState;
|
||||
import org.hibernate.cfg.PropertyData;
|
||||
|
@ -100,7 +99,6 @@ public class MapBinder extends CollectionBinder {
|
|||
mapKeyPropertyName,
|
||||
property,
|
||||
isEmbedded,
|
||||
buildingContext,
|
||||
mapKeyColumns,
|
||||
mapKeyManyToManyColumns,
|
||||
inverseJoinColumns != null ? inverseJoinColumns.getPropertyName() : null
|
||||
|
@ -123,7 +121,7 @@ public class MapBinder extends CollectionBinder {
|
|||
if ( selectable.isFormula() ) {
|
||||
throw new AssertionFailure( "Map key mapped by @MapKeyColumn is a Formula" );
|
||||
}
|
||||
Column column = (Column) selectable;
|
||||
final Column column = (Column) selectable;
|
||||
if ( !column.isNullable() ) {
|
||||
final PersistentClass persistentClass = ( ( OneToMany ) map.getElement() ).getAssociatedClass();
|
||||
// check if the index column has been mapped by the associated entity to a property;
|
||||
|
@ -158,207 +156,62 @@ public class MapBinder extends CollectionBinder {
|
|||
String mapKeyPropertyName,
|
||||
XProperty property,
|
||||
boolean isEmbedded,
|
||||
MetadataBuildingContext buildingContext,
|
||||
AnnotatedColumn[] mapKeyColumns,
|
||||
AnnotatedColumns mapKeyColumns,
|
||||
AnnotatedJoinColumns mapKeyManyToManyColumns,
|
||||
String targetPropertyName) {
|
||||
if ( mapKeyPropertyName != null ) {
|
||||
//this is an EJB3 @MapKey
|
||||
PersistentClass associatedClass = persistentClasses.get( elementType.getName() );
|
||||
if ( associatedClass == null ) {
|
||||
throw new AnnotationException( "Association '" + safeCollectionRole()
|
||||
+ "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
|
||||
}
|
||||
Property mapProperty = findPropertyByName( associatedClass, mapKeyPropertyName );
|
||||
if ( mapProperty == null ) {
|
||||
throw new AnnotationException( "Map key property '" + mapKeyPropertyName
|
||||
+ "' not found in target entity '" + associatedClass.getEntityName() + "'" );
|
||||
}
|
||||
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
|
||||
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
|
||||
InheritanceState inheritanceState = inheritanceStatePerClass.get( elementType );
|
||||
PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals( inheritanceState.getType() ) ?
|
||||
mapProperty.getPersistentClass() :
|
||||
associatedClass;
|
||||
Value indexValue = createFormulatedValue(
|
||||
mapProperty.getValue(), map, targetPropertyName, associatedClass, targetPropertyPersistentClass, buildingContext
|
||||
);
|
||||
map.setIndex( indexValue );
|
||||
map.setMapKeyPropertyName( mapKeyPropertyName );
|
||||
handleExplicitMapKey( elementType, persistentClasses, mapKeyPropertyName );
|
||||
}
|
||||
else {
|
||||
//this is a true Map mapping
|
||||
//TODO ugly copy/paste from CollectionBinder.bindManyToManySecondPass
|
||||
String mapKeyType;
|
||||
Class<?> target = void.class;
|
||||
/*
|
||||
* target has priority over reflection for the map key type
|
||||
* JPA 2 has priority
|
||||
*/
|
||||
if ( property.isAnnotationPresent( MapKeyClass.class ) ) {
|
||||
target = property.getAnnotation( MapKeyClass.class ).value();
|
||||
}
|
||||
if ( !void.class.equals( target ) ) {
|
||||
mapKeyType = target.getName();
|
||||
}
|
||||
else {
|
||||
mapKeyType = property.getMapKey().getName();
|
||||
}
|
||||
PersistentClass collectionEntity = persistentClasses.get( mapKeyType );
|
||||
boolean isIndexOfEntities = collectionEntity != null;
|
||||
ManyToOne element = null;
|
||||
org.hibernate.mapping.Map mapValue = (org.hibernate.mapping.Map) this.collection;
|
||||
final String mapKeyType = getKeyType( property );
|
||||
final PersistentClass collectionEntity = persistentClasses.get( mapKeyType );
|
||||
final boolean isIndexOfEntities = collectionEntity != null;
|
||||
final ManyToOne element;
|
||||
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
|
||||
if ( isIndexOfEntities ) {
|
||||
element = new ManyToOne( buildingContext, mapValue.getCollectionTable() );
|
||||
mapValue.setIndex( element );
|
||||
element.setReferencedEntityName( mapKeyType );
|
||||
//element.setFetchMode( fetchMode );
|
||||
//element.setLazy( fetchMode != FetchMode.JOIN );
|
||||
//make the second join non lazy
|
||||
element.setFetchMode( FetchMode.JOIN );
|
||||
element.setLazy( false );
|
||||
//does not make sense for a map key element.setIgnoreNotFound( ignoreNotFound );
|
||||
element = handleCollectionKeyedByEntities( buildingContext, mapKeyType, map );
|
||||
}
|
||||
else {
|
||||
final XClass keyXClass;
|
||||
AnnotatedClassType classType;
|
||||
element = null;
|
||||
final XClass keyClass;
|
||||
final AnnotatedClassType classType;
|
||||
if ( PRIMITIVE_NAMES.contains( mapKeyType ) ) {
|
||||
classType = AnnotatedClassType.NONE;
|
||||
keyXClass = null;
|
||||
keyClass = null;
|
||||
}
|
||||
else {
|
||||
final BootstrapContext bootstrapContext = buildingContext.getBootstrapContext();
|
||||
final Class<Object> mapKeyClass = bootstrapContext.getClassLoaderAccess().classForName( mapKeyType );
|
||||
keyXClass = bootstrapContext.getReflectionManager().toXClass( mapKeyClass );
|
||||
|
||||
classType = buildingContext.getMetadataCollector().getClassType( keyXClass );
|
||||
keyClass = bootstrapContext.getReflectionManager().toXClass( mapKeyClass );
|
||||
// force in case of attribute override naming the key
|
||||
if ( isEmbedded || mappingDefinedAttributeOverrideOnMapKey( property ) ) {
|
||||
classType = AnnotatedClassType.EMBEDDABLE;
|
||||
}
|
||||
classType = isEmbedded || mappingDefinedAttributeOverrideOnMapKey( property )
|
||||
? AnnotatedClassType.EMBEDDABLE
|
||||
: buildingContext.getMetadataCollector().getClassType( keyClass );
|
||||
}
|
||||
|
||||
CollectionPropertyHolder holder = buildPropertyHolder(
|
||||
mapValue,
|
||||
qualify( mapValue.getRole(), "mapkey" ),
|
||||
keyXClass,
|
||||
handleIndex(
|
||||
property,
|
||||
propertyHolder,
|
||||
buildingContext
|
||||
mapKeyColumns,
|
||||
mapKeyType,
|
||||
map,
|
||||
keyClass,
|
||||
classType,
|
||||
buildCollectionPropertyHolder( property, map, keyClass ),
|
||||
getAccessType( map )
|
||||
);
|
||||
|
||||
|
||||
// 'propertyHolder' is the PropertyHolder for the owner of the collection
|
||||
// 'holder' is the CollectionPropertyHolder.
|
||||
// 'property' is the collection XProperty
|
||||
propertyHolder.startingProperty( property );
|
||||
holder.prepare( property );
|
||||
|
||||
PersistentClass owner = mapValue.getOwner();
|
||||
AccessType accessType;
|
||||
// FIXME support @Access for collection of elements
|
||||
// String accessType = access != null ? access.value() : null;
|
||||
if ( owner.getIdentifierProperty() != null ) {
|
||||
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals( "property" )
|
||||
? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
|
||||
Property prop = owner.getIdentifierMapper().getProperties().get(0);
|
||||
accessType = prop.getPropertyAccessorName().equals( "property" )
|
||||
? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unable to guess collection property accessor name" );
|
||||
}
|
||||
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType(
|
||||
property,
|
||||
keyXClass,
|
||||
buildingContext
|
||||
);
|
||||
if ( AnnotatedClassType.EMBEDDABLE.equals( classType ) || compositeUserType != null ) {
|
||||
EntityBinder entityBinder = new EntityBinder();
|
||||
|
||||
PropertyData inferredData = isHibernateExtensionMapping()
|
||||
? new PropertyPreloadedData(AccessType.PROPERTY, "index", keyXClass)
|
||||
: new PropertyPreloadedData(AccessType.PROPERTY, "key", keyXClass);
|
||||
//"key" is the JPA 2 prefix for map keys
|
||||
|
||||
//TODO be smart with isNullable
|
||||
Component component = AnnotationBinder.fillComponent(
|
||||
holder,
|
||||
inferredData,
|
||||
accessType,
|
||||
true,
|
||||
entityBinder,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
compositeUserType,
|
||||
buildingContext,
|
||||
inheritanceStatePerClass
|
||||
);
|
||||
mapValue.setIndex( component );
|
||||
}
|
||||
else {
|
||||
final BasicValueBinder elementBinder = new BasicValueBinder( BasicValueBinder.Kind.MAP_KEY, buildingContext );
|
||||
elementBinder.setReturnedClassName( mapKeyType );
|
||||
|
||||
AnnotatedColumn[] elementColumns = mapKeyColumns;
|
||||
if ( elementColumns == null || elementColumns.length == 0 ) {
|
||||
elementColumns = new AnnotatedColumn[1];
|
||||
AnnotatedColumn column = new AnnotatedColumn();
|
||||
column.setImplicit( false );
|
||||
column.setNullable( true );
|
||||
column.setLength( Size.DEFAULT_LENGTH );
|
||||
column.setLogicalColumnName( Collection.DEFAULT_KEY_COLUMN_NAME );
|
||||
//TODO create an EMPTY_JOINS collection
|
||||
column.setJoins( new HashMap<>() );
|
||||
column.setBuildingContext( buildingContext );
|
||||
column.bind();
|
||||
elementColumns[0] = column;
|
||||
}
|
||||
//override the table
|
||||
for (AnnotatedColumn column : elementColumns) {
|
||||
column.setTable( mapValue.getCollectionTable() );
|
||||
}
|
||||
elementBinder.setColumns( elementColumns );
|
||||
//do not call setType as it extracts the type from @Type
|
||||
//the algorithm generally does not apply for map key anyway
|
||||
elementBinder.setType(
|
||||
property,
|
||||
keyXClass,
|
||||
this.collection.getOwnerEntityName(),
|
||||
holder.mapKeyAttributeConverterDescriptor( property, keyXClass )
|
||||
);
|
||||
elementBinder.setPersistentClassName( propertyHolder.getEntityName() );
|
||||
elementBinder.setAccessType( accessType );
|
||||
mapValue.setIndex( elementBinder.make() );
|
||||
}
|
||||
}
|
||||
//FIXME pass the Index Entity JoinColumns
|
||||
if ( !collection.isOneToMany() ) {
|
||||
//index column should not be null
|
||||
for ( AnnotatedJoinColumn col : mapKeyManyToManyColumns.getColumns() ) {
|
||||
col.forceNotNull();
|
||||
for ( AnnotatedJoinColumn column : mapKeyManyToManyColumns.getColumns() ) {
|
||||
column.forceNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
if ( element != null ) {
|
||||
final jakarta.persistence.ForeignKey foreignKey = getMapKeyForeignKey( property );
|
||||
if ( foreignKey != null ) {
|
||||
if ( foreignKey.value() == ConstraintMode.NO_CONSTRAINT
|
||||
|| foreignKey.value() == ConstraintMode.PROVIDER_DEFAULT
|
||||
&& getBuildingContext().getBuildingOptions().isNoConstraintByDefault() ) {
|
||||
element.disableForeignKey();
|
||||
}
|
||||
else {
|
||||
element.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
|
||||
element.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
|
||||
}
|
||||
}
|
||||
handleForeignKey( property, element );
|
||||
}
|
||||
|
||||
if ( isIndexOfEntities ) {
|
||||
|
@ -366,13 +219,185 @@ public class MapBinder extends CollectionBinder {
|
|||
collectionEntity,
|
||||
mapKeyManyToManyColumns,
|
||||
element,
|
||||
false, //a map key column has no unique constraint
|
||||
buildingContext
|
||||
false //a map key column has no unique constraint
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getKeyType(XProperty property) {
|
||||
//target has priority over reflection for the map key type
|
||||
//JPA 2 has priority
|
||||
final Class<?> target = property.isAnnotationPresent( MapKeyClass.class )
|
||||
? property.getAnnotation( MapKeyClass.class ).value()
|
||||
: void.class;
|
||||
return void.class.equals( target ) ? property.getMapKey().getName() : target.getName();
|
||||
}
|
||||
|
||||
private void handleExplicitMapKey(
|
||||
XClass elementType,
|
||||
Map<String, PersistentClass> persistentClasses,
|
||||
String mapKeyPropertyName) {
|
||||
final PersistentClass associatedClass = persistentClasses.get( elementType.getName() );
|
||||
if ( associatedClass == null ) {
|
||||
throw new AnnotationException( "Association '" + safeCollectionRole()
|
||||
+ "' targets the type '" + elementType.getName() + "' which is not an '@Entity' type" );
|
||||
}
|
||||
final Property mapProperty = findPropertyByName( associatedClass, mapKeyPropertyName);
|
||||
if ( mapProperty == null ) {
|
||||
throw new AnnotationException( "Map key property '" + mapKeyPropertyName
|
||||
+ "' not found in target entity '" + associatedClass.getEntityName() + "'" );
|
||||
}
|
||||
final org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
|
||||
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
|
||||
final InheritanceState inheritanceState = inheritanceStatePerClass.get(elementType);
|
||||
final PersistentClass targetEntity = InheritanceType.JOINED == inheritanceState.getType()
|
||||
? mapProperty.getPersistentClass()
|
||||
: associatedClass;
|
||||
final Value indexValue = createFormulatedValue( mapProperty.getValue(), map, associatedClass, targetEntity );
|
||||
map.setIndex( indexValue );
|
||||
map.setMapKeyPropertyName(mapKeyPropertyName);
|
||||
}
|
||||
|
||||
private CollectionPropertyHolder buildCollectionPropertyHolder(
|
||||
XProperty property,
|
||||
org.hibernate.mapping.Map map,
|
||||
XClass keyClass) {
|
||||
final CollectionPropertyHolder holder = buildPropertyHolder(
|
||||
map,
|
||||
qualify( map.getRole(), "mapkey" ),
|
||||
keyClass,
|
||||
property,
|
||||
propertyHolder,
|
||||
buildingContext
|
||||
);
|
||||
// 'propertyHolder' is the PropertyHolder for the owner of the collection
|
||||
// 'holder' is the CollectionPropertyHolder.
|
||||
// 'property' is the collection XProperty
|
||||
propertyHolder.startingProperty(property);
|
||||
holder.prepare(property);
|
||||
return holder;
|
||||
}
|
||||
|
||||
private void handleForeignKey(XProperty property, ManyToOne element) {
|
||||
final jakarta.persistence.ForeignKey foreignKey = getMapKeyForeignKey( property );
|
||||
if ( foreignKey != null ) {
|
||||
final ConstraintMode constraintMode = foreignKey.value();
|
||||
if ( constraintMode == ConstraintMode.NO_CONSTRAINT
|
||||
|| constraintMode == ConstraintMode.PROVIDER_DEFAULT
|
||||
&& getBuildingContext().getBuildingOptions().isNoConstraintByDefault() ) {
|
||||
element.disableForeignKey();
|
||||
}
|
||||
else {
|
||||
element.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
|
||||
element.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//similar to CollectionBinder.handleCollectionOfEntities()
|
||||
private static ManyToOne handleCollectionKeyedByEntities(
|
||||
MetadataBuildingContext context,
|
||||
String mapKeyType,
|
||||
org.hibernate.mapping.Map map) {
|
||||
final ManyToOne element;
|
||||
element = new ManyToOne(context, map.getCollectionTable() );
|
||||
map.setIndex( element );
|
||||
element.setReferencedEntityName(mapKeyType);
|
||||
//element.setFetchMode( fetchMode );
|
||||
//element.setLazy( fetchMode != FetchMode.JOIN );
|
||||
//make the second join non lazy
|
||||
element.setFetchMode( FetchMode.JOIN );
|
||||
element.setLazy( false );
|
||||
//does not make sense for a map key element.setIgnoreNotFound( ignoreNotFound );
|
||||
return element;
|
||||
}
|
||||
|
||||
private static AccessType getAccessType(org.hibernate.mapping.Map map) {
|
||||
final PersistentClass owner = map.getOwner();
|
||||
final AccessType accessType;
|
||||
// FIXME support @Access for collection of elements
|
||||
// String accessType = access != null ? access.value() : null;
|
||||
if ( owner.getIdentifierProperty() != null ) {
|
||||
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals( "property" )
|
||||
? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
|
||||
Property prop = owner.getIdentifierMapper().getProperties().get(0);
|
||||
accessType = prop.getPropertyAccessorName().equals( "property" )
|
||||
? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unable to guess collection property accessor name" );
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private void handleIndex(
|
||||
XProperty property,
|
||||
AnnotatedColumns mapKeyColumns,
|
||||
String mapKeyType,
|
||||
org.hibernate.mapping.Map map,
|
||||
XClass keyClass,
|
||||
AnnotatedClassType classType,
|
||||
CollectionPropertyHolder holder,
|
||||
AccessType accessType) {
|
||||
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType(
|
||||
property,
|
||||
keyClass,
|
||||
buildingContext
|
||||
);
|
||||
|
||||
if ( AnnotatedClassType.EMBEDDABLE == classType || compositeUserType != null ) {
|
||||
final EntityBinder entityBinder = new EntityBinder();
|
||||
final PropertyData inferredData = isHibernateExtensionMapping()
|
||||
? new PropertyPreloadedData( AccessType.PROPERTY, "index", keyClass)
|
||||
// "key" is the JPA 2 prefix for map keys
|
||||
: new PropertyPreloadedData( AccessType.PROPERTY, "key", keyClass);
|
||||
//TODO be smart with isNullable
|
||||
final Component component = AnnotationBinder.fillComponent(
|
||||
holder,
|
||||
inferredData,
|
||||
accessType,
|
||||
true,
|
||||
entityBinder,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
compositeUserType,
|
||||
buildingContext,
|
||||
inheritanceStatePerClass
|
||||
);
|
||||
map.setIndex( component );
|
||||
}
|
||||
else {
|
||||
final BasicValueBinder elementBinder = new BasicValueBinder( BasicValueBinder.Kind.MAP_KEY, buildingContext );
|
||||
elementBinder.setReturnedClassName(mapKeyType);
|
||||
final AnnotatedColumns keyColumns = createElementColumnsIfNecessary(
|
||||
collection,
|
||||
mapKeyColumns,
|
||||
Collection.DEFAULT_KEY_COLUMN_NAME,
|
||||
Size.DEFAULT_LENGTH, //TODO: is this really necessary??!!
|
||||
buildingContext
|
||||
);
|
||||
elementBinder.setColumns( keyColumns );
|
||||
//do not call setType as it extracts the type from @Type
|
||||
//the algorithm generally does not apply for map key anyway
|
||||
elementBinder.setType(
|
||||
property,
|
||||
keyClass,
|
||||
collection.getOwnerEntityName(),
|
||||
holder.mapKeyAttributeConverterDescriptor(property, keyClass)
|
||||
);
|
||||
elementBinder.setPersistentClassName( propertyHolder.getEntityName() );
|
||||
elementBinder.setAccessType(accessType);
|
||||
map.setIndex( elementBinder.make() );
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<? extends CompositeUserType<?>> resolveCompositeUserType(
|
||||
XProperty property,
|
||||
XClass returnedClass,
|
||||
|
@ -429,13 +454,11 @@ public class MapBinder extends CollectionBinder {
|
|||
return annotation.name().startsWith( "key." );
|
||||
}
|
||||
|
||||
protected Value createFormulatedValue(
|
||||
private Value createFormulatedValue(
|
||||
Value value,
|
||||
Collection collection,
|
||||
String targetPropertyName,
|
||||
PersistentClass associatedClass,
|
||||
PersistentClass targetPropertyPersistentClass,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
PersistentClass targetPropertyPersistentClass) {
|
||||
final Table mapKeyTable;
|
||||
// HHH-11005 - only if we are OneToMany and location of map key property is at a different level, need to add a select
|
||||
if ( !associatedClass.equals( targetPropertyPersistentClass ) ) {
|
||||
|
@ -464,14 +487,7 @@ public class MapBinder extends CollectionBinder {
|
|||
newProperty.setPropertyAccessorName( current.getPropertyAccessorName() );
|
||||
newProperty.setSelectable( current.isSelectable() );
|
||||
newProperty.setValue(
|
||||
createFormulatedValue(
|
||||
current.getValue(),
|
||||
collection,
|
||||
targetPropertyName,
|
||||
associatedClass,
|
||||
associatedClass,
|
||||
buildingContext
|
||||
)
|
||||
createFormulatedValue( current.getValue(), collection, associatedClass, associatedClass )
|
||||
);
|
||||
indexComponent.addProperty( newProperty );
|
||||
}
|
||||
|
@ -504,8 +520,8 @@ public class MapBinder extends CollectionBinder {
|
|||
SimpleValue sourceValue = (SimpleValue) value;
|
||||
SimpleValue targetValue;
|
||||
if ( value instanceof ManyToOne ) {
|
||||
ManyToOne sourceManyToOne = (ManyToOne) sourceValue;
|
||||
ManyToOne targetManyToOne = new ManyToOne( getBuildingContext(), mapKeyTable );
|
||||
final ManyToOne sourceManyToOne = (ManyToOne) sourceValue;
|
||||
final ManyToOne targetManyToOne = new ManyToOne( getBuildingContext(), mapKeyTable );
|
||||
targetManyToOne.setFetchMode( FetchMode.DEFAULT );
|
||||
targetManyToOne.setLazy( true );
|
||||
//targetValue.setIgnoreNotFound( ); does not make sense for a map key
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.annotations.common.reflection.XClass;
|
|||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.cfg.AccessType;
|
||||
import org.hibernate.cfg.AnnotatedColumns;
|
||||
import org.hibernate.cfg.AnnotationBinder;
|
||||
import org.hibernate.cfg.AnnotatedColumn;
|
||||
import org.hibernate.cfg.InheritanceState;
|
||||
|
@ -66,7 +67,7 @@ public class PropertyBinder {
|
|||
private boolean lazy;
|
||||
private String lazyGroup;
|
||||
private AccessType accessType;
|
||||
private AnnotatedColumn[] columns;
|
||||
private AnnotatedColumns columns;
|
||||
private PropertyHolder holder;
|
||||
private Value value;
|
||||
private boolean insertable = true;
|
||||
|
@ -128,9 +129,10 @@ public class PropertyBinder {
|
|||
this.accessType = accessType;
|
||||
}
|
||||
|
||||
public void setColumns(AnnotatedColumn[] columns) {
|
||||
insertable = columns[0].isInsertable();
|
||||
updatable = columns[0].isUpdatable();
|
||||
public void setColumns(AnnotatedColumns columns) {
|
||||
final AnnotatedColumn firstColumn = columns.getColumns()[0];
|
||||
insertable = firstColumn.isInsertable();
|
||||
updatable = firstColumn.isUpdatable();
|
||||
//consistency is checked later when we know the property name
|
||||
this.columns = columns;
|
||||
}
|
||||
|
@ -233,7 +235,7 @@ public class PropertyBinder {
|
|||
|
||||
private Property bind(Property prop) {
|
||||
if ( isId ) {
|
||||
final RootClass rootClass = ( RootClass ) holder.getPersistentClass();
|
||||
final RootClass rootClass = (RootClass) holder.getPersistentClass();
|
||||
//if an xToMany, it has to be wrapped today.
|
||||
//FIXME this poses a problem as the PK is the class instead of the associated class which is not really compliant with the spec
|
||||
if ( isXToMany || entityBinder.wrapIdsInEmbeddedComponents() ) {
|
||||
|
@ -257,7 +259,7 @@ public class PropertyBinder {
|
|||
}
|
||||
else {
|
||||
rootClass.setIdentifier( (KeyValue) getValue() );
|
||||
if (embedded) {
|
||||
if ( embedded ) {
|
||||
rootClass.setEmbeddedIdentifier( true );
|
||||
}
|
||||
else {
|
||||
|
@ -267,7 +269,7 @@ public class PropertyBinder {
|
|||
inheritanceStatePerClass,
|
||||
buildingContext
|
||||
);
|
||||
if (superclass != null) {
|
||||
if ( superclass != null ) {
|
||||
superclass.setDeclaredIdentifierProperty(prop);
|
||||
}
|
||||
else {
|
||||
|
@ -355,7 +357,7 @@ public class PropertyBinder {
|
|||
prop.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
|
||||
}
|
||||
else if ( property != null && property.isAnnotationPresent(OptimisticLock.class) ) {
|
||||
OptimisticLock lockAnn = property.getAnnotation(OptimisticLock.class);
|
||||
final OptimisticLock lockAnn = property.getAnnotation(OptimisticLock.class);
|
||||
validateOptimisticLock(lockAnn);
|
||||
prop.setOptimisticLocked( !lockAnn.excluded() );
|
||||
}
|
||||
|
|
|
@ -274,7 +274,6 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
|
|||
@Override
|
||||
public void addColumn(Column incomingColumn, boolean isInsertable, boolean isUpdatable) {
|
||||
super.addColumn( incomingColumn, isInsertable, isUpdatable );
|
||||
|
||||
checkSelectable( incomingColumn );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue