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