use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class InFlightMetadataCollectorImpl method processExportableProducers.
private void processExportableProducers(MetadataBuildingContext buildingContext) {
// for now we only handle id generators as ExportableProducers
final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect();
final String defaultCatalog = extractName(getDatabase().getDefaultNamespace().getName().getCatalog(), dialect);
final String defaultSchema = extractName(getDatabase().getDefaultNamespace().getName().getSchema(), dialect);
for (PersistentClass entityBinding : entityBindingMap.values()) {
if (entityBinding.isInherited()) {
continue;
}
handleIdentifierValueBinding(entityBinding.getIdentifier(), dialect, defaultCatalog, defaultSchema, (RootClass) entityBinding);
}
for (Collection collection : collectionBindingMap.values()) {
if (!IdentifierCollection.class.isInstance(collection)) {
continue;
}
handleIdentifierValueBinding(((IdentifierCollection) collection).getIdentifier(), dialect, defaultCatalog, defaultSchema, null);
}
}
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 = null;
if (properties != null) {
//todo how about properties.size() == 1, this should be much simpler
Component embeddedComp = columnOwner instanceof PersistentClass ? new Component(context.getMetadataCollector(), (PersistentClass) columnOwner) : new Component(context.getMetadataCollector(), (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 CollectionBinder method getCollectionBinder.
/**
* collection binder factory
*/
public static CollectionBinder getCollectionBinder(String entityName, XProperty property, boolean isIndexed, boolean isHibernateExtensionMapping, MetadataBuildingContext buildingContext) {
final CollectionBinder result;
if (property.isArray()) {
if (property.getElementClass().isPrimitive()) {
result = new PrimitiveArrayBinder();
} else {
result = new ArrayBinder();
}
} else if (property.isCollection()) {
//TODO consider using an XClass
Class returnedClass = property.getCollectionClass();
if (java.util.Set.class.equals(returnedClass)) {
if (property.isAnnotationPresent(CollectionId.class)) {
throw new AnnotationException("Set do not support @CollectionId: " + StringHelper.qualify(entityName, property.getName()));
}
result = new SetBinder(false);
} else if (java.util.SortedSet.class.equals(returnedClass)) {
if (property.isAnnotationPresent(CollectionId.class)) {
throw new AnnotationException("Set do not support @CollectionId: " + StringHelper.qualify(entityName, property.getName()));
}
result = new SetBinder(true);
} else if (java.util.Map.class.equals(returnedClass)) {
if (property.isAnnotationPresent(CollectionId.class)) {
throw new AnnotationException("Map do not support @CollectionId: " + StringHelper.qualify(entityName, property.getName()));
}
result = new MapBinder(false);
} else if (java.util.SortedMap.class.equals(returnedClass)) {
if (property.isAnnotationPresent(CollectionId.class)) {
throw new AnnotationException("Map do not support @CollectionId: " + StringHelper.qualify(entityName, property.getName()));
}
result = new MapBinder(true);
} else if (java.util.Collection.class.equals(returnedClass)) {
if (property.isAnnotationPresent(CollectionId.class)) {
result = new IdBagBinder();
} else {
result = new BagBinder();
}
} else if (java.util.List.class.equals(returnedClass)) {
if (isIndexed) {
if (property.isAnnotationPresent(CollectionId.class)) {
throw new AnnotationException("List do not support @CollectionId and @OrderColumn (or @IndexColumn) at the same time: " + StringHelper.qualify(entityName, property.getName()));
}
result = new ListBinder();
} else if (property.isAnnotationPresent(CollectionId.class)) {
result = new IdBagBinder();
} else {
result = new BagBinder();
}
} else {
throw new AnnotationException(returnedClass.getName() + " collection not yet supported: " + StringHelper.qualify(entityName, property.getName()));
}
} else {
throw new AnnotationException("Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: " + StringHelper.qualify(entityName, property.getName()));
}
result.setIsHibernateExtensionMapping(isHibernateExtensionMapping);
final CollectionType typeAnnotation = property.getAnnotation(CollectionType.class);
if (typeAnnotation != null) {
final String typeName = typeAnnotation.type();
// see if it names a type-def
final TypeDefinition typeDef = buildingContext.getMetadataCollector().getTypeDefinition(typeName);
if (typeDef != null) {
result.explicitType = typeDef.getTypeImplementorClass().getName();
result.explicitTypeParameters.putAll(typeDef.getParameters());
} else {
result.explicitType = typeName;
for (Parameter param : typeAnnotation.parameters()) {
result.explicitTypeParameters.setProperty(param.name(), param.value());
}
}
}
return result;
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class CollectionBinder method bindManyToManySecondPass.
protected void bindManyToManySecondPass(Collection collValue, Map persistentClasses, Ejb3JoinColumn[] joinColumns, Ejb3JoinColumn[] inverseJoinColumns, Ejb3Column[] elementColumns, boolean isEmbedded, XClass collType, boolean ignoreNotFound, boolean unique, boolean cascadeDeleteEnabled, TableBinder associationTableBinder, XProperty property, PropertyHolder parentPropertyHolder, MetadataBuildingContext buildingContext) throws MappingException {
if (property == null) {
throw new IllegalArgumentException("null was passed for argument property");
}
final PersistentClass collectionEntity = (PersistentClass) persistentClasses.get(collType.getName());
final String hqlOrderBy = extractHqlOrderBy(jpaOrderBy);
boolean isCollectionOfEntities = collectionEntity != null;
ManyToAny anyAnn = property.getAnnotation(ManyToAny.class);
if (LOG.isDebugEnabled()) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
if (isCollectionOfEntities && unique) {
LOG.debugf("Binding a OneToMany: %s through an association table", path);
} else if (isCollectionOfEntities) {
LOG.debugf("Binding as ManyToMany: %s", path);
} else if (anyAnn != null) {
LOG.debugf("Binding a ManyToAny: %s", path);
} else {
LOG.debugf("Binding a collection of element: %s", path);
}
}
//check for user error
if (!isCollectionOfEntities) {
if (property.isAnnotationPresent(ManyToMany.class) || property.isAnnotationPresent(OneToMany.class)) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("Use of @OneToMany or @ManyToMany targeting an unmapped class: " + path + "[" + collType + "]");
} else if (anyAnn != null) {
if (parentPropertyHolder.getJoinTable(property) == null) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("@JoinTable is mandatory when @ManyToAny is used: " + path);
}
} else {
JoinTable joinTableAnn = parentPropertyHolder.getJoinTable(property);
if (joinTableAnn != null && joinTableAnn.inverseJoinColumns().length > 0) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
throw new AnnotationException("Use of @JoinTable.inverseJoinColumns targeting an unmapped class: " + path + "[" + collType + "]");
}
}
}
boolean mappedBy = !BinderHelper.isEmptyAnnotationValue(joinColumns[0].getMappedBy());
if (mappedBy) {
if (!isCollectionOfEntities) {
StringBuilder error = new StringBuilder(80).append("Collection of elements must not have mappedBy or association reference an unmapped entity: ").append(collValue.getOwnerEntityName()).append(".").append(joinColumns[0].getPropertyName());
throw new AnnotationException(error.toString());
}
Property otherSideProperty;
try {
otherSideProperty = collectionEntity.getRecursiveProperty(joinColumns[0].getMappedBy());
} catch (MappingException e) {
throw new AnnotationException("mappedBy reference an unknown target entity property: " + collType + "." + joinColumns[0].getMappedBy() + " in " + collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName());
}
Table table;
if (otherSideProperty.getValue() instanceof Collection) {
//this is a collection on the other side
table = ((Collection) otherSideProperty.getValue()).getCollectionTable();
} else {
//This is a ToOne with a @JoinTable or a regular property
table = otherSideProperty.getValue().getTable();
}
collValue.setCollectionTable(table);
String entityName = collectionEntity.getEntityName();
for (Ejb3JoinColumn column : joinColumns) {
//column.setDefaultColumnHeader( joinColumns[0].getMappedBy() ); //seems not to be used, make sense
column.setManyToManyOwnerSideEntityName(entityName);
}
} else {
//FIXME NamingStrategy
for (Ejb3JoinColumn column : joinColumns) {
String mappedByProperty = buildingContext.getMetadataCollector().getFromMappedBy(collValue.getOwnerEntityName(), column.getPropertyName());
Table ownerTable = collValue.getOwner().getTable();
column.setMappedBy(collValue.getOwner().getEntityName(), collValue.getOwner().getJpaEntityName(), buildingContext.getMetadataCollector().getLogicalTableName(ownerTable), mappedByProperty);
// String header = ( mappedByProperty == null ) ? mappings.getLogicalTableName( ownerTable ) : mappedByProperty;
// column.setDefaultColumnHeader( header );
}
if (StringHelper.isEmpty(associationTableBinder.getName())) {
//default value
associationTableBinder.setDefaultName(collValue.getOwner().getClassName(), collValue.getOwner().getEntityName(), collValue.getOwner().getJpaEntityName(), buildingContext.getMetadataCollector().getLogicalTableName(collValue.getOwner().getTable()), collectionEntity != null ? collectionEntity.getClassName() : null, collectionEntity != null ? collectionEntity.getEntityName() : null, collectionEntity != null ? collectionEntity.getJpaEntityName() : null, collectionEntity != null ? buildingContext.getMetadataCollector().getLogicalTableName(collectionEntity.getTable()) : null, joinColumns[0].getPropertyName());
}
associationTableBinder.setJPA2ElementCollection(!isCollectionOfEntities && property.isAnnotationPresent(ElementCollection.class));
collValue.setCollectionTable(associationTableBinder.bind());
}
bindFilters(isCollectionOfEntities);
bindCollectionSecondPass(collValue, collectionEntity, joinColumns, cascadeDeleteEnabled, property, propertyHolder, buildingContext);
ManyToOne element = null;
if (isCollectionOfEntities) {
element = new ManyToOne(buildingContext.getMetadataCollector(), collValue.getCollectionTable());
collValue.setElement(element);
element.setReferencedEntityName(collType.getName());
//element.setFetchMode( fetchMode );
//element.setLazy( fetchMode != FetchMode.JOIN );
//make the second join non lazy
element.setFetchMode(FetchMode.JOIN);
element.setLazy(false);
element.setIgnoreNotFound(ignoreNotFound);
// as per 11.1.38 of JPA 2.0 spec, default to primary key if no column is specified by @OrderBy.
if (hqlOrderBy != null) {
collValue.setManyToManyOrdering(buildOrderByClauseFromHql(hqlOrderBy, collectionEntity, collValue.getRole()));
}
final ForeignKey fk = property.getAnnotation(ForeignKey.class);
if (fk != null && !BinderHelper.isEmptyAnnotationValue(fk.name())) {
element.setForeignKeyName(fk.name());
} else {
final JoinTable joinTableAnn = property.getAnnotation(JoinTable.class);
if (joinTableAnn != null) {
String foreignKeyName = joinTableAnn.inverseForeignKey().name();
String foreignKeyDefinition = joinTableAnn.inverseForeignKey().foreignKeyDefinition();
ConstraintMode foreignKeyValue = joinTableAnn.inverseForeignKey().value();
if (joinTableAnn.inverseJoinColumns().length != 0) {
final JoinColumn joinColumnAnn = joinTableAnn.inverseJoinColumns()[0];
if ("".equals(foreignKeyName)) {
foreignKeyName = joinColumnAnn.foreignKey().name();
foreignKeyDefinition = joinColumnAnn.foreignKey().foreignKeyDefinition();
}
if (foreignKeyValue != ConstraintMode.NO_CONSTRAINT) {
foreignKeyValue = joinColumnAnn.foreignKey().value();
}
}
if (joinTableAnn.inverseForeignKey().value() == ConstraintMode.NO_CONSTRAINT) {
element.setForeignKeyName("none");
} else {
element.setForeignKeyName(StringHelper.nullIfEmpty(foreignKeyName));
element.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKeyDefinition));
}
}
}
} else if (anyAnn != null) {
//@ManyToAny
//Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class
PropertyData inferredData = new PropertyInferredData(null, property, "unsupported", buildingContext.getBuildingOptions().getReflectionManager());
//override the table
for (Ejb3Column column : inverseJoinColumns) {
column.setTable(collValue.getCollectionTable());
}
Any any = BinderHelper.buildAnyValue(anyAnn.metaDef(), inverseJoinColumns, anyAnn.metaColumn(), inferredData, cascadeDeleteEnabled, Nullability.NO_CONSTRAINT, propertyHolder, new EntityBinder(), true, buildingContext);
collValue.setElement(any);
} else {
XClass elementClass;
AnnotatedClassType classType;
CollectionPropertyHolder holder = null;
if (BinderHelper.PRIMITIVE_NAMES.contains(collType.getName())) {
classType = AnnotatedClassType.NONE;
elementClass = null;
holder = PropertyHolderBuilder.buildPropertyHolder(collValue, collValue.getRole(), null, property, parentPropertyHolder, buildingContext);
} else {
elementClass = collType;
classType = buildingContext.getMetadataCollector().getClassType(elementClass);
holder = PropertyHolderBuilder.buildPropertyHolder(collValue, collValue.getRole(), elementClass, property, parentPropertyHolder, buildingContext);
// 'parentPropertyHolder' is the PropertyHolder for the owner of the collection
// 'holder' is the CollectionPropertyHolder.
// 'property' is the collection XProperty
parentPropertyHolder.startingProperty(property);
//force in case of attribute override
boolean attributeOverride = property.isAnnotationPresent(AttributeOverride.class) || property.isAnnotationPresent(AttributeOverrides.class);
// todo : force in the case of Convert annotation(s) with embedded paths (beyond key/value prefixes)?
if (isEmbedded || attributeOverride) {
classType = AnnotatedClassType.EMBEDDABLE;
}
}
if (AnnotatedClassType.EMBEDDABLE.equals(classType)) {
holder.prepare(property);
EntityBinder entityBinder = new EntityBinder();
PersistentClass owner = collValue.getOwner();
boolean isPropertyAnnotated;
//String accessType = access != null ? access.value() : null;
if (owner.getIdentifierProperty() != null) {
isPropertyAnnotated = owner.getIdentifierProperty().getPropertyAccessorName().equals("property");
} else if (owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0) {
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
isPropertyAnnotated = prop.getPropertyAccessorName().equals("property");
} else {
throw new AssertionFailure("Unable to guess collection property accessor name");
}
PropertyData inferredData;
if (isMap()) {
//"value" is the JPA 2 prefix for map values (used to be "element")
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "element", elementClass);
} else {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "value", elementClass);
}
} else {
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "element", elementClass);
} else {
//"collection&&element" is not a valid property name => placeholder
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "collection&&element", elementClass);
}
}
//TODO be smart with isNullable
boolean isNullable = true;
Component component = AnnotationBinder.fillComponent(holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, isNullable, entityBinder, false, false, true, buildingContext, inheritanceStatePerClass);
collValue.setElement(component);
if (StringHelper.isNotEmpty(hqlOrderBy)) {
String path = collValue.getOwnerEntityName() + "." + joinColumns[0].getPropertyName();
String orderBy = adjustUserSuppliedValueCollectionOrderingFragment(hqlOrderBy);
if (orderBy != null) {
collValue.setOrderBy(orderBy);
}
}
} else {
holder.prepare(property);
SimpleValueBinder elementBinder = new SimpleValueBinder();
elementBinder.setBuildingContext(buildingContext);
elementBinder.setReturnedClassName(collType.getName());
if (elementColumns == null || elementColumns.length == 0) {
elementColumns = new Ejb3Column[1];
Ejb3Column column = new Ejb3Column();
column.setImplicit(false);
//not following the spec but more clean
column.setNullable(true);
column.setLength(Ejb3Column.DEFAULT_COLUMN_LENGTH);
column.setLogicalColumnName(Collection.DEFAULT_ELEMENT_COLUMN_NAME);
//TODO create an EMPTY_JOINS collection
column.setJoins(new HashMap<String, Join>());
column.setBuildingContext(buildingContext);
column.bind();
elementColumns[0] = column;
}
//override the table
for (Ejb3Column column : elementColumns) {
column.setTable(collValue.getCollectionTable());
}
elementBinder.setColumns(elementColumns);
elementBinder.setType(property, elementClass, collValue.getOwnerEntityName(), holder.resolveElementAttributeConverterDescriptor(property, elementClass));
elementBinder.setPersistentClassName(propertyHolder.getEntityName());
elementBinder.setAccessType(accessType);
collValue.setElement(elementBinder.make());
String orderBy = adjustUserSuppliedValueCollectionOrderingFragment(hqlOrderBy);
if (orderBy != null) {
collValue.setOrderBy(orderBy);
}
}
}
checkFilterConditions(collValue);
//FIXME: do optional = false
if (isCollectionOfEntities) {
bindManytoManyInverseFk(collectionEntity, inverseJoinColumns, element, unique, buildingContext);
}
}
use of org.hibernate.mapping.Collection in project hibernate-orm by hibernate.
the class CollectionBinder method bindManytoManyInverseFk.
/**
* bind the inverse FK of a ManyToMany
* If we are in a mappedBy case, read the columns from the associated
* collection element
* Otherwise delegates to the usual algorithm
*/
public static void bindManytoManyInverseFk(PersistentClass referencedEntity, Ejb3JoinColumn[] columns, SimpleValue value, boolean unique, MetadataBuildingContext buildingContext) {
final String mappedBy = columns[0].getMappedBy();
if (StringHelper.isNotEmpty(mappedBy)) {
final Property property = referencedEntity.getRecursiveProperty(mappedBy);
Iterator mappedByColumns;
if (property.getValue() instanceof Collection) {
mappedByColumns = ((Collection) property.getValue()).getKey().getColumnIterator();
} else {
//find the appropriate reference key, can be in a join
Iterator joinsIt = referencedEntity.getJoinIterator();
KeyValue key = null;
while (joinsIt.hasNext()) {
Join join = (Join) joinsIt.next();
if (join.containsProperty(property)) {
key = join.getKey();
break;
}
}
if (key == null)
key = property.getPersistentClass().getIdentifier();
mappedByColumns = key.getColumnIterator();
}
while (mappedByColumns.hasNext()) {
Column column = (Column) mappedByColumns.next();
columns[0].linkValueUsingAColumnCopy(column, value);
}
String referencedPropertyName = buildingContext.getMetadataCollector().getPropertyReferencedAssociation("inverse__" + referencedEntity.getEntityName(), mappedBy);
if (referencedPropertyName != null) {
//TODO always a many to one?
((ManyToOne) value).setReferencedPropertyName(referencedPropertyName);
buildingContext.getMetadataCollector().addUniquePropertyReference(referencedEntity.getEntityName(), referencedPropertyName);
}
((ManyToOne) value).setReferenceToPrimaryKey(referencedPropertyName == null);
value.createForeignKey();
} else {
BinderHelper.createSyntheticPropertyReference(columns, referencedEntity, null, value, true, buildingContext);
TableBinder.bindFk(referencedEntity, null, columns, value, unique, buildingContext);
}
}
Aggregations