use of org.hibernate.mapping.DependantValue in project hibernate-orm by hibernate.
the class ModelBinder method bindSecondaryTable.
private void bindSecondaryTable(MappingDocument mappingDocument, SecondaryTableSource secondaryTableSource, Join secondaryTableJoin, final EntityTableXref entityTableXref) {
final PersistentClass persistentClass = secondaryTableJoin.getPersistentClass();
final Identifier catalogName = determineCatalogName(secondaryTableSource.getTableSource());
final Identifier schemaName = determineSchemaName(secondaryTableSource.getTableSource());
final Namespace namespace = database.locateNamespace(catalogName, schemaName);
Table secondaryTable;
final Identifier logicalTableName;
if (TableSource.class.isInstance(secondaryTableSource.getTableSource())) {
final TableSource tableSource = (TableSource) secondaryTableSource.getTableSource();
logicalTableName = database.toIdentifier(tableSource.getExplicitTableName());
secondaryTable = namespace.locateTable(logicalTableName);
if (secondaryTable == null) {
secondaryTable = namespace.createTable(logicalTableName, false);
} else {
secondaryTable.setAbstract(false);
}
secondaryTable.setComment(tableSource.getComment());
} else {
final InLineViewSource inLineViewSource = (InLineViewSource) secondaryTableSource.getTableSource();
secondaryTable = new Table(namespace, inLineViewSource.getSelectStatement(), false);
logicalTableName = Identifier.toIdentifier(inLineViewSource.getLogicalName());
}
secondaryTableJoin.setTable(secondaryTable);
entityTableXref.addSecondaryTable(mappingDocument, logicalTableName, secondaryTableJoin);
bindCustomSql(mappingDocument, secondaryTableSource, secondaryTableJoin);
secondaryTableJoin.setSequentialSelect(secondaryTableSource.getFetchStyle() == FetchStyle.SELECT);
secondaryTableJoin.setInverse(secondaryTableSource.isInverse());
secondaryTableJoin.setOptional(secondaryTableSource.isOptional());
if (log.isDebugEnabled()) {
log.debugf("Mapping entity secondary-table: %s -> %s", persistentClass.getEntityName(), secondaryTable.getName());
}
final SimpleValue keyBinding = new DependantValue(mappingDocument.getMetadataCollector(), secondaryTable, persistentClass.getIdentifier());
if (mappingDocument.getBuildingOptions().useNationalizedCharacterData()) {
keyBinding.makeNationalized();
}
secondaryTableJoin.setKey(keyBinding);
keyBinding.setCascadeDeleteEnabled(secondaryTableSource.isCascadeDeleteEnabled());
// NOTE : no Type info to bind...
relationalObjectBinder.bindColumns(mappingDocument, secondaryTableSource.getPrimaryKeyColumnSources(), keyBinding, secondaryTableSource.isOptional(), new RelationalObjectBinder.ColumnNamingDelegate() {
int count = 0;
@Override
public Identifier determineImplicitName(LocalMetadataBuildingContext context) {
final Column correspondingColumn = entityTableXref.getPrimaryTable().getPrimaryKey().getColumn(count++);
return database.toIdentifier(correspondingColumn.getQuotedName());
}
});
keyBinding.setForeignKeyName(secondaryTableSource.getExplicitForeignKeyName());
// skip creating primary and foreign keys for a subselect.
if (secondaryTable.getSubselect() == null) {
secondaryTableJoin.createPrimaryKey();
secondaryTableJoin.createForeignKey();
}
}
use of org.hibernate.mapping.DependantValue in project hibernate-orm by hibernate.
the class AnnotationBinder method bindClass.
/**
* Bind a class having JSR175 annotations. Subclasses <b>have to</b> be bound afterQuery its parent class.
*
* @param clazzToProcess entity to bind as {@code XClass} instance
* @param inheritanceStatePerClass Meta data about the inheritance relationships for all mapped classes
*
* @throws MappingException in case there is an configuration error
*/
public static void bindClass(XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, MetadataBuildingContext context) throws MappingException {
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
if (clazzToProcess.isAnnotationPresent(Entity.class) && clazzToProcess.isAnnotationPresent(MappedSuperclass.class)) {
throw new AnnotationException("An entity cannot be annotated with both @Entity and @MappedSuperclass: " + clazzToProcess.getName());
}
//TODO: be more strict with secondarytable allowance (not for ids, not for secondary table join columns etc)
InheritanceState inheritanceState = inheritanceStatePerClass.get(clazzToProcess);
AnnotatedClassType classType = context.getMetadataCollector().getClassType(clazzToProcess);
//Queries declared in MappedSuperclass should be usable in Subclasses
if (AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals(classType)) {
bindQueries(clazzToProcess, context);
bindTypeDefs(clazzToProcess, context);
bindFilterDefs(clazzToProcess, context);
}
if (!isEntityClassType(clazzToProcess, classType)) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debugf("Binding entity from annotated class: %s", clazzToProcess.getName());
}
PersistentClass superEntity = getSuperEntity(clazzToProcess, inheritanceStatePerClass, context, inheritanceState);
PersistentClass persistentClass = makePersistentClass(inheritanceState, superEntity, context);
Entity entityAnn = clazzToProcess.getAnnotation(Entity.class);
org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(org.hibernate.annotations.Entity.class);
EntityBinder entityBinder = new EntityBinder(entityAnn, hibEntityAnn, clazzToProcess, persistentClass, context);
entityBinder.setInheritanceState(inheritanceState);
bindQueries(clazzToProcess, context);
bindFilterDefs(clazzToProcess, context);
bindTypeDefs(clazzToProcess, context);
bindFetchProfiles(clazzToProcess, context);
BinderHelper.bindAnyMetaDefs(clazzToProcess, context);
String schema = "";
//might be no @Table annotation on the annotated class
String table = "";
String catalog = "";
List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
javax.persistence.Table tabAnn = null;
if (clazzToProcess.isAnnotationPresent(javax.persistence.Table.class)) {
tabAnn = clazzToProcess.getAnnotation(javax.persistence.Table.class);
table = tabAnn.name();
schema = tabAnn.schema();
catalog = tabAnn.catalog();
uniqueConstraints = TableBinder.buildUniqueConstraintHolders(tabAnn.uniqueConstraints());
}
Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(clazzToProcess, context, inheritanceState, superEntity);
final Ejb3DiscriminatorColumn discriminatorColumn;
if (InheritanceType.SINGLE_TABLE.equals(inheritanceState.getType())) {
discriminatorColumn = processSingleTableDiscriminatorProperties(clazzToProcess, context, inheritanceState, entityBinder);
} else if (InheritanceType.JOINED.equals(inheritanceState.getType())) {
discriminatorColumn = processJoinedDiscriminatorProperties(clazzToProcess, context, inheritanceState, entityBinder);
} else {
discriminatorColumn = null;
}
entityBinder.setProxy(clazzToProcess.getAnnotation(Proxy.class));
entityBinder.setBatchSize(clazzToProcess.getAnnotation(BatchSize.class));
entityBinder.setWhere(clazzToProcess.getAnnotation(Where.class));
entityBinder.setCache(determineCacheSettings(clazzToProcess, context));
entityBinder.setNaturalIdCache(clazzToProcess, clazzToProcess.getAnnotation(NaturalIdCache.class));
bindFilters(clazzToProcess, entityBinder, context);
entityBinder.bindEntity();
if (inheritanceState.hasTable()) {
Check checkAnn = clazzToProcess.getAnnotation(Check.class);
String constraints = checkAnn == null ? null : checkAnn.constraints();
EntityTableXref denormalizedTableXref = inheritanceState.hasDenormalizedTable() ? context.getMetadataCollector().getEntityTableXref(superEntity.getEntityName()) : null;
entityBinder.bindTable(schema, catalog, table, uniqueConstraints, constraints, denormalizedTableXref);
} else {
if (clazzToProcess.isAnnotationPresent(Table.class)) {
LOG.invalidTableAnnotation(clazzToProcess.getName());
}
if (inheritanceState.getType() == InheritanceType.SINGLE_TABLE) {
// we at least need to properly set up the EntityTableXref
entityBinder.bindTableForDiscriminatedSubclass(context.getMetadataCollector().getEntityTableXref(superEntity.getEntityName()));
}
}
PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(clazzToProcess, persistentClass, entityBinder, context, inheritanceStatePerClass);
javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(javax.persistence.SecondaryTable.class);
javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(javax.persistence.SecondaryTables.class);
entityBinder.firstLevelSecondaryTablesBinding(secTabAnn, secTabsAnn);
OnDelete onDeleteAnn = clazzToProcess.getAnnotation(OnDelete.class);
boolean onDeleteAppropriate = false;
// todo : sucks that this is separate from RootClass distinction
final boolean isInheritanceRoot = !inheritanceState.hasParents();
final boolean hasSubclasses = inheritanceState.hasSiblings();
if (InheritanceType.JOINED.equals(inheritanceState.getType())) {
if (inheritanceState.hasParents()) {
onDeleteAppropriate = true;
final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
SimpleValue key = new DependantValue(context.getMetadataCollector(), jsc.getTable(), jsc.getIdentifier());
jsc.setKey(key);
ForeignKey fk = clazzToProcess.getAnnotation(ForeignKey.class);
if (fk != null && !BinderHelper.isEmptyAnnotationValue(fk.name())) {
key.setForeignKeyName(fk.name());
} else {
final PrimaryKeyJoinColumn pkJoinColumn = clazzToProcess.getAnnotation(PrimaryKeyJoinColumn.class);
final PrimaryKeyJoinColumns pkJoinColumns = clazzToProcess.getAnnotation(PrimaryKeyJoinColumns.class);
if (pkJoinColumns != null && pkJoinColumns.foreignKey().value() == ConstraintMode.NO_CONSTRAINT) {
// don't apply a constraint based on ConstraintMode
key.setForeignKeyName("none");
} else if (pkJoinColumns != null && !StringHelper.isEmpty(pkJoinColumns.foreignKey().name())) {
key.setForeignKeyName(pkJoinColumns.foreignKey().name());
} else if (pkJoinColumn != null && pkJoinColumn.foreignKey().value() == ConstraintMode.NO_CONSTRAINT) {
// don't apply a constraint based on ConstraintMode
key.setForeignKeyName("none");
} else if (pkJoinColumn != null && !StringHelper.isEmpty(pkJoinColumn.foreignKey().name())) {
key.setForeignKeyName(pkJoinColumn.foreignKey().name());
}
}
if (onDeleteAnn != null) {
key.setCascadeDeleteEnabled(OnDeleteAction.CASCADE.equals(onDeleteAnn.action()));
} else {
key.setCascadeDeleteEnabled(false);
}
//we are never in a second pass at that stage, so queue it
context.getMetadataCollector().addSecondPass(new JoinedSubclassFkSecondPass(jsc, inheritanceJoinedColumns, key, context));
context.getMetadataCollector().addSecondPass(new CreateKeySecondPass(jsc));
}
if (isInheritanceRoot) {
// (it is perfectly valid for joined subclasses to not have discriminators).
if (discriminatorColumn != null) {
// we have a discriminator column
if (hasSubclasses || !discriminatorColumn.isImplicit()) {
bindDiscriminatorColumnToRootPersistentClass((RootClass) persistentClass, discriminatorColumn, entityBinder.getSecondaryTables(), propertyHolder, context);
//bind it again since the type might have changed
entityBinder.bindDiscriminatorValue();
}
}
}
} else if (InheritanceType.SINGLE_TABLE.equals(inheritanceState.getType())) {
if (isInheritanceRoot) {
if (hasSubclasses || !discriminatorColumn.isImplicit()) {
bindDiscriminatorColumnToRootPersistentClass((RootClass) persistentClass, discriminatorColumn, entityBinder.getSecondaryTables(), propertyHolder, context);
//bind it again since the type might have changed
entityBinder.bindDiscriminatorValue();
}
}
}
if (onDeleteAnn != null && !onDeleteAppropriate) {
LOG.invalidOnDeleteAnnotation(propertyHolder.getEntityName());
}
// try to find class level generators
HashMap<String, IdentifierGeneratorDefinition> classGenerators = buildLocalGenerators(clazzToProcess, context);
// check properties
final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();
inheritanceState.postProcess(persistentClass, entityBinder);
final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE && inheritanceState.hasParents();
Set<String> idPropertiesIfIdClass = new HashSet<String>();
boolean isIdClass = mapAsIdClass(inheritanceStatePerClass, inheritanceState, persistentClass, entityBinder, propertyHolder, elementsToProcess, idPropertiesIfIdClass, context);
if (!isIdClass) {
entityBinder.setWrapIdsInEmbeddedComponents(elementsToProcess.getIdPropertyCount() > 1);
}
processIdPropertiesIfNotAlready(inheritanceStatePerClass, context, persistentClass, entityBinder, propertyHolder, classGenerators, elementsToProcess, subclassAndSingleTableStrategy, idPropertiesIfIdClass);
if (!inheritanceState.hasParents()) {
final RootClass rootClass = (RootClass) persistentClass;
context.getMetadataCollector().addSecondPass(new CreateKeySecondPass(rootClass));
} else {
superEntity.addSubclass((Subclass) persistentClass);
}
context.getMetadataCollector().addEntityBinding(persistentClass);
//Process secondary tables and complementary definitions (ie o.h.a.Table)
context.getMetadataCollector().addSecondPass(new SecondaryTableSecondPass(entityBinder, propertyHolder, clazzToProcess));
//add process complementary Table definition (index & all)
entityBinder.processComplementaryTableDefinitions(clazzToProcess.getAnnotation(org.hibernate.annotations.Table.class));
entityBinder.processComplementaryTableDefinitions(clazzToProcess.getAnnotation(org.hibernate.annotations.Tables.class));
entityBinder.processComplementaryTableDefinitions(tabAnn);
}
use of org.hibernate.mapping.DependantValue in project hibernate-orm by hibernate.
the class CollectionBinder method buildCollectionKey.
private static SimpleValue buildCollectionKey(Collection collValue, Ejb3JoinColumn[] joinColumns, boolean cascadeDeleteEnabled, XProperty property, PropertyHolder propertyHolder, MetadataBuildingContext buildingContext) {
//binding key reference using column
KeyValue keyVal;
//has to do that here because the referencedProperty creation happens in a FKSecondPass for Many to one yuk!
if (joinColumns.length > 0 && StringHelper.isNotEmpty(joinColumns[0].getMappedBy())) {
String entityName = joinColumns[0].getManyToManyOwnerSideEntityName() != null ? "inverse__" + joinColumns[0].getManyToManyOwnerSideEntityName() : joinColumns[0].getPropertyHolder().getEntityName();
String propRef = buildingContext.getMetadataCollector().getPropertyReferencedAssociation(entityName, joinColumns[0].getMappedBy());
if (propRef != null) {
collValue.setReferencedPropertyName(propRef);
buildingContext.getMetadataCollector().addPropertyReference(collValue.getOwnerEntityName(), propRef);
}
}
String propRef = collValue.getReferencedPropertyName();
if (propRef == null) {
keyVal = collValue.getOwner().getIdentifier();
} else {
keyVal = (KeyValue) collValue.getOwner().getReferencedProperty(propRef).getValue();
}
DependantValue key = new DependantValue(buildingContext.getMetadataCollector(), collValue.getCollectionTable(), keyVal);
key.setTypeName(null);
Ejb3Column.checkPropertyConsistency(joinColumns, collValue.getOwnerEntityName());
key.setNullable(joinColumns.length == 0 || joinColumns[0].isNullable());
key.setUpdateable(joinColumns.length == 0 || joinColumns[0].isUpdatable());
key.setCascadeDeleteEnabled(cascadeDeleteEnabled);
collValue.setKey(key);
if (property != null) {
final ForeignKey fk = property.getAnnotation(ForeignKey.class);
if (fk != null && !BinderHelper.isEmptyAnnotationValue(fk.name())) {
key.setForeignKeyName(fk.name());
} else {
final CollectionTable collectionTableAnn = property.getAnnotation(CollectionTable.class);
if (collectionTableAnn != null) {
if (collectionTableAnn.foreignKey().value() == ConstraintMode.NO_CONSTRAINT) {
key.setForeignKeyName("none");
} else {
key.setForeignKeyName(StringHelper.nullIfEmpty(collectionTableAnn.foreignKey().name()));
key.setForeignKeyDefinition(StringHelper.nullIfEmpty(collectionTableAnn.foreignKey().foreignKeyDefinition()));
}
} else {
final JoinTable joinTableAnn = property.getAnnotation(JoinTable.class);
if (joinTableAnn != null) {
String foreignKeyName = joinTableAnn.foreignKey().name();
String foreignKeyDefinition = joinTableAnn.foreignKey().foreignKeyDefinition();
ConstraintMode foreignKeyValue = joinTableAnn.foreignKey().value();
if (joinTableAnn.joinColumns().length != 0) {
final JoinColumn joinColumnAnn = joinTableAnn.joinColumns()[0];
if ("".equals(foreignKeyName)) {
foreignKeyName = joinColumnAnn.foreignKey().name();
foreignKeyDefinition = joinColumnAnn.foreignKey().foreignKeyDefinition();
}
if (foreignKeyValue != ConstraintMode.NO_CONSTRAINT) {
foreignKeyValue = joinColumnAnn.foreignKey().value();
}
}
if (foreignKeyValue == ConstraintMode.NO_CONSTRAINT) {
key.setForeignKeyName("none");
} else {
key.setForeignKeyName(StringHelper.nullIfEmpty(foreignKeyName));
key.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKeyDefinition));
}
} else {
final javax.persistence.ForeignKey fkOverride = propertyHolder.getOverriddenForeignKey(StringHelper.qualify(propertyHolder.getPath(), property.getName()));
if (fkOverride != null && fkOverride.value() == ConstraintMode.NO_CONSTRAINT) {
key.setForeignKeyName("none");
} else if (fkOverride != null) {
key.setForeignKeyName(StringHelper.nullIfEmpty(fkOverride.name()));
key.setForeignKeyDefinition(StringHelper.nullIfEmpty(fkOverride.foreignKeyDefinition()));
} else {
final JoinColumn joinColumnAnn = property.getAnnotation(JoinColumn.class);
if (joinColumnAnn != null) {
if (joinColumnAnn.foreignKey().value() == ConstraintMode.NO_CONSTRAINT) {
key.setForeignKeyName("none");
} else {
key.setForeignKeyName(StringHelper.nullIfEmpty(joinColumnAnn.foreignKey().name()));
key.setForeignKeyDefinition(StringHelper.nullIfEmpty(joinColumnAnn.foreignKey().foreignKeyDefinition()));
}
}
}
}
}
}
}
return key;
}
use of org.hibernate.mapping.DependantValue in project hibernate-orm by hibernate.
the class MapBinder method createFormulatedValue.
protected Value createFormulatedValue(Value value, Collection collection, String targetPropertyName, PersistentClass associatedClass, PersistentClass targetPropertyPersistentClass, MetadataBuildingContext buildingContext) {
Value element = collection.getElement();
String fromAndWhere = null;
if (!(element instanceof OneToMany)) {
String referencedPropertyName = null;
if (element instanceof ToOne) {
referencedPropertyName = ((ToOne) element).getReferencedPropertyName();
} else if (element instanceof DependantValue) {
//TODO this never happen I think
if (propertyName != null) {
referencedPropertyName = collection.getReferencedPropertyName();
} else {
throw new AnnotationException("SecondaryTable JoinColumn cannot reference a non primary key");
}
}
Iterator<Selectable> referencedEntityColumns;
if (referencedPropertyName == null) {
referencedEntityColumns = associatedClass.getIdentifier().getColumnIterator();
} else {
Property referencedProperty = associatedClass.getRecursiveProperty(referencedPropertyName);
referencedEntityColumns = referencedProperty.getColumnIterator();
}
fromAndWhere = getFromAndWhereFormula(associatedClass.getTable().getName(), element.getColumnIterator(), referencedEntityColumns);
} else {
// 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)) {
fromAndWhere = getFromAndWhereFormula(targetPropertyPersistentClass.getTable().getQualifiedTableName().toString(), element.getColumnIterator(), associatedClass.getIdentifier().getColumnIterator());
}
}
if (value instanceof Component) {
Component component = (Component) value;
Iterator properties = component.getPropertyIterator();
Component indexComponent = new Component(getBuildingContext().getMetadataCollector(), collection);
indexComponent.setComponentClassName(component.getComponentClassName());
while (properties.hasNext()) {
Property current = (Property) properties.next();
Property newProperty = new Property();
newProperty.setCascade(current.getCascade());
newProperty.setValueGenerationStrategy(current.getValueGenerationStrategy());
newProperty.setInsertable(false);
newProperty.setUpdateable(false);
newProperty.setMetaAttributes(current.getMetaAttributes());
newProperty.setName(current.getName());
newProperty.setNaturalIdentifier(false);
//newProperty.setOptimisticLocked( false );
newProperty.setOptional(false);
newProperty.setPersistentClass(current.getPersistentClass());
newProperty.setPropertyAccessorName(current.getPropertyAccessorName());
newProperty.setSelectable(current.isSelectable());
newProperty.setValue(createFormulatedValue(current.getValue(), collection, targetPropertyName, associatedClass, associatedClass, buildingContext));
indexComponent.addProperty(newProperty);
}
return indexComponent;
} else if (value instanceof SimpleValue) {
SimpleValue sourceValue = (SimpleValue) value;
SimpleValue targetValue;
if (value instanceof ManyToOne) {
ManyToOne sourceManyToOne = (ManyToOne) sourceValue;
ManyToOne targetManyToOne = new ManyToOne(getBuildingContext().getMetadataCollector(), collection.getCollectionTable());
targetManyToOne.setFetchMode(FetchMode.DEFAULT);
targetManyToOne.setLazy(true);
//targetValue.setIgnoreNotFound( ); does not make sense for a map key
targetManyToOne.setReferencedEntityName(sourceManyToOne.getReferencedEntityName());
targetValue = targetManyToOne;
} else {
targetValue = new SimpleValue(getBuildingContext().getMetadataCollector(), collection.getCollectionTable());
targetValue.copyTypeFrom(sourceValue);
}
Iterator columns = sourceValue.getColumnIterator();
Random random = new Random();
while (columns.hasNext()) {
Object current = columns.next();
Formula formula = new Formula();
String formulaString;
if (current instanceof Column) {
formulaString = ((Column) current).getQuotedName();
} else if (current instanceof Formula) {
formulaString = ((Formula) current).getFormula();
} else {
throw new AssertionFailure("Unknown element in column iterator: " + current.getClass());
}
if (fromAndWhere != null) {
formulaString = Template.renderWhereStringTemplate(formulaString, "$alias$", new HSQLDialect());
formulaString = "(select " + formulaString + fromAndWhere + ")";
formulaString = StringHelper.replace(formulaString, "$alias$", "a" + random.nextInt(16));
}
formula.setFormula(formulaString);
targetValue.addFormula(formula);
}
return targetValue;
} else {
throw new AssertionFailure("Unknown type encounters for map key: " + value.getClass());
}
}
use of org.hibernate.mapping.DependantValue in project hibernate-orm by hibernate.
the class TableBinder method bindFk.
public static void bindFk(PersistentClass referencedEntity, PersistentClass destinationEntity, Ejb3JoinColumn[] columns, SimpleValue value, boolean unique, MetadataBuildingContext buildingContext) {
PersistentClass associatedClass;
if (destinationEntity != null) {
//overridden destination
associatedClass = destinationEntity;
} else {
associatedClass = columns[0].getPropertyHolder() == null ? null : columns[0].getPropertyHolder().getPersistentClass();
}
final String mappedByProperty = columns[0].getMappedBy();
if (StringHelper.isNotEmpty(mappedByProperty)) {
/**
* Get the columns of the mapped-by property
* copy them and link the copy to the actual value
*/
LOG.debugf("Retrieving property %s.%s", associatedClass.getEntityName(), mappedByProperty);
final Property property = associatedClass.getRecursiveProperty(columns[0].getMappedBy());
Iterator mappedByColumns;
if (property.getValue() instanceof Collection) {
Collection collection = ((Collection) property.getValue());
Value element = collection.getElement();
if (element == null) {
throw new AnnotationException("Illegal use of mappedBy on both sides of the relationship: " + associatedClass.getEntityName() + "." + mappedByProperty);
}
mappedByColumns = element.getColumnIterator();
} else {
mappedByColumns = property.getValue().getColumnIterator();
}
while (mappedByColumns.hasNext()) {
Column column = (Column) mappedByColumns.next();
columns[0].overrideFromReferencedColumnIfNecessary(column);
columns[0].linkValueUsingAColumnCopy(column, value);
}
} else if (columns[0].isImplicit()) {
/**
* if columns are implicit, then create the columns based on the
* referenced entity id columns
*/
Iterator idColumns;
if (referencedEntity instanceof JoinedSubclass) {
idColumns = referencedEntity.getKey().getColumnIterator();
} else {
idColumns = referencedEntity.getIdentifier().getColumnIterator();
}
while (idColumns.hasNext()) {
Column column = (Column) idColumns.next();
columns[0].linkValueUsingDefaultColumnNaming(column, referencedEntity, value);
columns[0].overrideFromReferencedColumnIfNecessary(column);
}
} else {
int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType(columns, referencedEntity, buildingContext);
if (Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum) {
String referencedPropertyName;
if (value instanceof ToOne) {
referencedPropertyName = ((ToOne) value).getReferencedPropertyName();
} else if (value instanceof DependantValue) {
String propertyName = columns[0].getPropertyName();
if (propertyName != null) {
Collection collection = (Collection) referencedEntity.getRecursiveProperty(propertyName).getValue();
referencedPropertyName = collection.getReferencedPropertyName();
} else {
throw new AnnotationException("SecondaryTable JoinColumn cannot reference a non primary key");
}
} else {
throw new AssertionFailure("Do a property ref on an unexpected Value type: " + value.getClass().getName());
}
if (referencedPropertyName == null) {
throw new AssertionFailure("No property ref found while expected");
}
Property synthProp = referencedEntity.getReferencedProperty(referencedPropertyName);
if (synthProp == null) {
throw new AssertionFailure("Cannot find synthProp: " + referencedEntity.getEntityName() + "." + referencedPropertyName);
}
linkJoinColumnWithValueOverridingNameIfImplicit(referencedEntity, synthProp.getColumnIterator(), columns, value);
} else {
if (Ejb3JoinColumn.NO_REFERENCE == fkEnum) {
//implicit case, we hope PK and FK columns are in the same order
if (columns.length != referencedEntity.getIdentifier().getColumnSpan()) {
throw new AnnotationException("A Foreign key refering " + referencedEntity.getEntityName() + " from " + associatedClass.getEntityName() + " has the wrong number of column. should be " + referencedEntity.getIdentifier().getColumnSpan());
}
linkJoinColumnWithValueOverridingNameIfImplicit(referencedEntity, referencedEntity.getIdentifier().getColumnIterator(), columns, value);
} else {
//explicit referencedColumnName
Iterator idColItr = referencedEntity.getKey().getColumnIterator();
org.hibernate.mapping.Column col;
//works cause the pk has to be on the primary table
Table table = referencedEntity.getTable();
if (!idColItr.hasNext()) {
LOG.debug("No column in the identifier!");
}
while (idColItr.hasNext()) {
boolean match = false;
//for each PK column, find the associated FK column.
col = (org.hibernate.mapping.Column) idColItr.next();
for (Ejb3JoinColumn joinCol : columns) {
String referencedColumn = joinCol.getReferencedColumn();
referencedColumn = buildingContext.getMetadataCollector().getPhysicalColumnName(table, referencedColumn);
//In JPA 2 referencedColumnName is case insensitive
if (referencedColumn.equalsIgnoreCase(col.getQuotedName(buildingContext.getMetadataCollector().getDatabase().getJdbcEnvironment().getDialect()))) {
//proper join column
if (joinCol.isNameDeferred()) {
joinCol.linkValueUsingDefaultColumnNaming(col, referencedEntity, value);
} else {
joinCol.linkWithValue(value);
}
joinCol.overrideFromReferencedColumnIfNecessary(col);
match = true;
break;
}
}
if (!match) {
throw new AnnotationException("Column name " + col.getName() + " of " + referencedEntity.getEntityName() + " not found in JoinColumns.referencedColumnName");
}
}
}
}
}
value.createForeignKey();
if (unique) {
createUniqueConstraint(value);
}
}
Aggregations