use of org.hibernate.mapping.Collection 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);
}
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class BinderHelper method createSyntheticPropertyReference.
// This is sooooooooo close in terms of not generating a synthetic property if we do not have to (where property ref
// refers to a single property). The sticking point is cases where the `referencedPropertyName` come from subclasses
// or secondary tables. Part of the problem is in PersistentClass itself during attempts to resolve the referenced
// property; currently it only considers non-subclass and non-joined properties. Part of the problem is in terms
// of SQL generation.
// public static void createSyntheticPropertyReference(
// Ejb3JoinColumn[] columns,
// PersistentClass ownerEntity,
// PersistentClass associatedEntity,
// Value value,
// boolean inverse,
// Mappings mappings) {
// //associated entity only used for more precise exception, yuk!
// if ( columns[0].isImplicit() || StringHelper.isNotEmpty( columns[0].getMappedBy() ) ) return;
// int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType( columns, ownerEntity, mappings );
// PersistentClass associatedClass = columns[0].getPropertyHolder() != null ?
// columns[0].getPropertyHolder().getPersistentClass() :
// null;
// if ( Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum ) {
// //find properties associated to a certain column
// Object columnOwner = findColumnOwner( ownerEntity, columns[0].getReferencedColumn(), mappings );
// List<Property> properties = findPropertiesByColumns( columnOwner, columns, mappings );
//
// if ( properties == null ) {
// //TODO use a ToOne type doing a second select
// StringBuilder columnsList = new StringBuilder();
// columnsList.append( "referencedColumnNames(" );
// for (Ejb3JoinColumn column : columns) {
// columnsList.append( column.getReferencedColumn() ).append( ", " );
// }
// columnsList.setLength( columnsList.length() - 2 );
// columnsList.append( ") " );
//
// if ( associatedEntity != null ) {
// //overidden destination
// columnsList.append( "of " )
// .append( associatedEntity.getEntityName() )
// .append( "." )
// .append( columns[0].getPropertyName() )
// .append( " " );
// }
// else {
// if ( columns[0].getPropertyHolder() != null ) {
// columnsList.append( "of " )
// .append( columns[0].getPropertyHolder().getEntityName() )
// .append( "." )
// .append( columns[0].getPropertyName() )
// .append( " " );
// }
// }
// columnsList.append( "referencing " )
// .append( ownerEntity.getEntityName() )
// .append( " not mapped to a single property" );
// throw new AnnotationException( columnsList.toString() );
// }
//
// final String referencedPropertyName;
//
// if ( properties.size() == 1 ) {
// referencedPropertyName = properties.get(0).getName();
// }
// else {
// // Create a synthetic (embedded composite) property to use as the referenced property which
// // contains all the properties mapped to the referenced columns. We need to make a shallow copy
// // of the properties to mark them as non-insertable/updatable.
//
// // todo : what if the columns all match with an existing component?
//
// StringBuilder propertyNameBuffer = new StringBuilder( "_" );
// propertyNameBuffer.append( associatedClass.getEntityName().replace( '.', '_' ) );
// propertyNameBuffer.append( "_" ).append( columns[0].getPropertyName() );
// String syntheticPropertyName = propertyNameBuffer.toString();
// //create an embeddable component
//
// //todo how about properties.size() == 1, this should be much simpler
// Component embeddedComp = columnOwner instanceof PersistentClass ?
// new Component( mappings, (PersistentClass) columnOwner ) :
// new Component( mappings, (Join) columnOwner );
// embeddedComp.setEmbedded( true );
// embeddedComp.setNodeName( syntheticPropertyName );
// embeddedComp.setComponentClassName( embeddedComp.getOwner().getClassName() );
// for (Property property : properties) {
// Property clone = BinderHelper.shallowCopy( property );
// clone.setInsertable( false );
// clone.setUpdateable( false );
// clone.setNaturalIdentifier( false );
// clone.setGeneration( property.getGeneration() );
// embeddedComp.addProperty( clone );
// }
// SyntheticProperty synthProp = new SyntheticProperty();
// synthProp.setName( syntheticPropertyName );
// synthProp.setNodeName( syntheticPropertyName );
// synthProp.setPersistentClass( ownerEntity );
// synthProp.setUpdateable( false );
// synthProp.setInsertable( false );
// synthProp.setValue( embeddedComp );
// synthProp.setPropertyAccessorName( "embedded" );
// ownerEntity.addProperty( synthProp );
// //make it unique
// TableBinder.createUniqueConstraint( embeddedComp );
//
// referencedPropertyName = syntheticPropertyName;
// }
//
// /**
// * creating the property ref to the new synthetic property
// */
// if ( value instanceof ToOne ) {
// ( (ToOne) value ).setReferencedPropertyName( referencedPropertyName );
// mappings.addUniquePropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
// }
// else if ( value instanceof Collection ) {
// ( (Collection) value ).setReferencedPropertyName( referencedPropertyName );
// //not unique because we could create a mtm wo association table
// mappings.addPropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
// }
// else {
// throw new AssertionFailure(
// "Do a property ref on an unexpected Value type: "
// + value.getClass().getName()
// );
// }
// mappings.addPropertyReferencedAssociation(
// ( inverse ? "inverse__" : "" ) + associatedClass.getEntityName(),
// columns[0].getPropertyName(),
// referencedPropertyName
// );
// }
// }
public static void createSyntheticPropertyReference(Ejb3JoinColumn[] columns, PersistentClass ownerEntity, PersistentClass associatedEntity, Value value, boolean inverse, MetadataBuildingContext context) {
// associated entity only used for more precise exception, yuk!
if (columns[0].isImplicit() || StringHelper.isNotEmpty(columns[0].getMappedBy())) {
return;
}
int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType(columns, ownerEntity, context);
PersistentClass associatedClass = columns[0].getPropertyHolder() != null ? columns[0].getPropertyHolder().getPersistentClass() : null;
if (Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum) {
/**
* Create a synthetic property to refer to including an
* embedded component value containing all the properties
* mapped to the referenced columns
* We need to shallow copy those properties to mark them
* as non insertable / non updatable
*/
StringBuilder propertyNameBuffer = new StringBuilder("_");
propertyNameBuffer.append(associatedClass.getEntityName().replace('.', '_'));
propertyNameBuffer.append("_").append(columns[0].getPropertyName().replace('.', '_'));
String syntheticPropertyName = propertyNameBuffer.toString();
// find properties associated to a certain column
Object columnOwner = findColumnOwner(ownerEntity, columns[0].getReferencedColumn(), context);
List<Property> properties = findPropertiesByColumns(columnOwner, columns, context);
// create an embeddable component
Property synthProp;
if (properties != null) {
// todo how about properties.size() == 1, this should be much simpler
Component embeddedComp = columnOwner instanceof PersistentClass ? new Component(context, (PersistentClass) columnOwner) : new Component(context, (Join) columnOwner);
embeddedComp.setEmbedded(true);
embeddedComp.setComponentClassName(embeddedComp.getOwner().getClassName());
for (Property property : properties) {
Property clone = BinderHelper.shallowCopy(property);
clone.setInsertable(false);
clone.setUpdateable(false);
clone.setNaturalIdentifier(false);
clone.setValueGenerationStrategy(property.getValueGenerationStrategy());
embeddedComp.addProperty(clone);
}
synthProp = new SyntheticProperty();
synthProp.setName(syntheticPropertyName);
synthProp.setPersistentClass(ownerEntity);
synthProp.setUpdateable(false);
synthProp.setInsertable(false);
synthProp.setValue(embeddedComp);
synthProp.setPropertyAccessorName("embedded");
ownerEntity.addProperty(synthProp);
// make it unique
TableBinder.createUniqueConstraint(embeddedComp);
} else {
// TODO use a ToOne type doing a second select
StringBuilder columnsList = new StringBuilder();
columnsList.append("referencedColumnNames(");
for (Ejb3JoinColumn column : columns) {
columnsList.append(column.getReferencedColumn()).append(", ");
}
columnsList.setLength(columnsList.length() - 2);
columnsList.append(") ");
if (associatedEntity != null) {
// overidden destination
columnsList.append("of ").append(associatedEntity.getEntityName()).append(".").append(columns[0].getPropertyName()).append(" ");
} else {
if (columns[0].getPropertyHolder() != null) {
columnsList.append("of ").append(columns[0].getPropertyHolder().getEntityName()).append(".").append(columns[0].getPropertyName()).append(" ");
}
}
columnsList.append("referencing ").append(ownerEntity.getEntityName()).append(" not mapped to a single property");
throw new AnnotationException(columnsList.toString());
}
/**
* creating the property ref to the new synthetic property
*/
if (value instanceof ToOne) {
((ToOne) value).setReferencedPropertyName(syntheticPropertyName);
((ToOne) value).setReferenceToPrimaryKey(syntheticPropertyName == null);
context.getMetadataCollector().addUniquePropertyReference(ownerEntity.getEntityName(), syntheticPropertyName);
} else if (value instanceof Collection) {
((Collection) value).setReferencedPropertyName(syntheticPropertyName);
// not unique because we could create a mtm wo association table
context.getMetadataCollector().addPropertyReference(ownerEntity.getEntityName(), syntheticPropertyName);
} else {
throw new AssertionFailure("Do a property ref on an unexpected Value type: " + value.getClass().getName());
}
context.getMetadataCollector().addPropertyReferencedAssociation((inverse ? "inverse__" : "") + associatedClass.getEntityName(), columns[0].getPropertyName(), syntheticPropertyName);
}
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class PersisterTest method testCollectionPersisterSpecified.
@Test
public void testCollectionPersisterSpecified() throws Exception {
// tests the persister specified by the @Persister annotation on a collection
Collection collection = metadata().getCollectionBinding(Deck.class.getName() + ".cards");
assertEquals("Incorrect Persister class for collection " + collection.getRole(), CollectionPersister.class, collection.getCollectionPersisterClass());
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class BaseNonConfigCoreFunctionalTestCase method applyCacheSettings.
protected final void applyCacheSettings(Metadata metadata) {
if (!overrideCacheStrategy()) {
return;
}
if (getCacheConcurrencyStrategy() == null) {
return;
}
for (PersistentClass entityBinding : metadata.getEntityBindings()) {
if (entityBinding.isInherited()) {
continue;
}
boolean hasLob = false;
final Iterator props = entityBinding.getPropertyClosureIterator();
while (props.hasNext()) {
final Property prop = (Property) props.next();
if (prop.getValue().isSimpleValue()) {
if (isLob(((SimpleValue) prop.getValue()).getTypeName())) {
hasLob = true;
break;
}
}
}
if (!hasLob) {
((RootClass) entityBinding).setCacheConcurrencyStrategy(getCacheConcurrencyStrategy());
entityBinding.setCached(true);
}
}
for (Collection collectionBinding : metadata.getCollectionBindings()) {
boolean isLob = false;
if (collectionBinding.getElement().isSimpleValue()) {
isLob = isLob(((SimpleValue) collectionBinding.getElement()).getTypeName());
}
if (!isLob) {
collectionBinding.setCacheConcurrencyStrategy(getCacheConcurrencyStrategy());
}
}
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class CorrectnessTestCase method buildMetadata.
private Metadata buildMetadata(StandardServiceRegistry registry) {
MetadataSources metadataSources = new MetadataSources(registry);
for (Class entityClass : getAnnotatedClasses()) {
metadataSources.addAnnotatedClass(entityClass);
}
Metadata metadata = metadataSources.buildMetadata();
for (PersistentClass entityBinding : metadata.getEntityBindings()) {
if (!entityBinding.isInherited()) {
((RootClass) entityBinding).setCacheConcurrencyStrategy(accessType.getExternalName());
}
}
// Collections don't have integrated version, these piggyback on parent's owner version (for DB).
// However, this version number isn't extractable and is not passed to cache methods.
AccessType collectionAccessType = accessType == AccessType.NONSTRICT_READ_WRITE ? AccessType.READ_WRITE : accessType;
for (Collection collectionBinding : metadata.getCollectionBindings()) {
collectionBinding.setCacheConcurrencyStrategy(collectionAccessType.getExternalName());
}
return metadata;
}
Aggregations