Search in sources :

Example 6 with Collection

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);
    }
}
Also used : Dialect(org.hibernate.dialect.Dialect) Collection(org.hibernate.mapping.Collection) IdentifierCollection(org.hibernate.mapping.IdentifierCollection) PersistentClass(org.hibernate.mapping.PersistentClass) IdentifierCollection(org.hibernate.mapping.IdentifierCollection)

Example 7 with Collection

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);
    }
}
Also used : AssertionFailure(org.hibernate.AssertionFailure) SyntheticProperty(org.hibernate.mapping.SyntheticProperty) Join(org.hibernate.mapping.Join) ToOne(org.hibernate.mapping.ToOne) AnnotationException(org.hibernate.AnnotationException) Collection(org.hibernate.mapping.Collection) Component(org.hibernate.mapping.Component) Property(org.hibernate.mapping.Property) SyntheticProperty(org.hibernate.mapping.SyntheticProperty) PersistentClass(org.hibernate.mapping.PersistentClass)

Example 8 with Collection

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;
}
Also used : TypeDefinition(org.hibernate.boot.model.TypeDefinition) CollectionId(org.hibernate.annotations.CollectionId) CollectionType(org.hibernate.annotations.CollectionType) AnnotationException(org.hibernate.AnnotationException) LazyCollection(org.hibernate.annotations.LazyCollection) Collection(org.hibernate.mapping.Collection) ElementCollection(javax.persistence.ElementCollection) Parameter(org.hibernate.annotations.Parameter) PersistentClass(org.hibernate.mapping.PersistentClass) XClass(org.hibernate.annotations.common.reflection.XClass) Map(java.util.Map) BinderHelper.toAliasTableMap(org.hibernate.cfg.BinderHelper.toAliasTableMap) HashMap(java.util.HashMap) BinderHelper.toAliasEntityMap(org.hibernate.cfg.BinderHelper.toAliasEntityMap)

Example 9 with Collection

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);
    }
}
Also used : PropertyData(org.hibernate.cfg.PropertyData) HashMap(java.util.HashMap) PropertyInferredData(org.hibernate.cfg.PropertyInferredData) PropertyPreloadedData(org.hibernate.cfg.PropertyPreloadedData) Any(org.hibernate.mapping.Any) ManyToAny(org.hibernate.annotations.ManyToAny) XClass(org.hibernate.annotations.common.reflection.XClass) ManyToOne(org.hibernate.mapping.ManyToOne) MappingException(org.hibernate.MappingException) ManyToAny(org.hibernate.annotations.ManyToAny) JoinColumn(javax.persistence.JoinColumn) Ejb3JoinColumn(org.hibernate.cfg.Ejb3JoinColumn) AnnotationException(org.hibernate.AnnotationException) Ejb3Column(org.hibernate.cfg.Ejb3Column) Component(org.hibernate.mapping.Component) Property(org.hibernate.mapping.Property) XProperty(org.hibernate.annotations.common.reflection.XProperty) PersistentClass(org.hibernate.mapping.PersistentClass) JoinTable(javax.persistence.JoinTable) CollectionTable(javax.persistence.CollectionTable) WhereJoinTable(org.hibernate.annotations.WhereJoinTable) Table(org.hibernate.mapping.Table) FilterJoinTable(org.hibernate.annotations.FilterJoinTable) CollectionPropertyHolder(org.hibernate.cfg.CollectionPropertyHolder) AssertionFailure(org.hibernate.annotations.common.AssertionFailure) ManyToMany(javax.persistence.ManyToMany) ConstraintMode(javax.persistence.ConstraintMode) OneToMany(javax.persistence.OneToMany) ForeignKey(org.hibernate.annotations.ForeignKey) LazyCollection(org.hibernate.annotations.LazyCollection) Collection(org.hibernate.mapping.Collection) ElementCollection(javax.persistence.ElementCollection) Ejb3JoinColumn(org.hibernate.cfg.Ejb3JoinColumn) AnnotatedClassType(org.hibernate.cfg.AnnotatedClassType) JoinTable(javax.persistence.JoinTable) WhereJoinTable(org.hibernate.annotations.WhereJoinTable) FilterJoinTable(org.hibernate.annotations.FilterJoinTable)

Example 10 with Collection

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);
    }
}
Also used : KeyValue(org.hibernate.mapping.KeyValue) Ejb3Column(org.hibernate.cfg.Ejb3Column) MapKeyColumn(javax.persistence.MapKeyColumn) Column(org.hibernate.mapping.Column) IndexColumn(org.hibernate.cfg.IndexColumn) JoinColumn(javax.persistence.JoinColumn) Ejb3JoinColumn(org.hibernate.cfg.Ejb3JoinColumn) Iterator(java.util.Iterator) LazyCollection(org.hibernate.annotations.LazyCollection) Collection(org.hibernate.mapping.Collection) ElementCollection(javax.persistence.ElementCollection) Join(org.hibernate.mapping.Join) Property(org.hibernate.mapping.Property) XProperty(org.hibernate.annotations.common.reflection.XProperty) ManyToOne(org.hibernate.mapping.ManyToOne)

Aggregations

Collection (org.hibernate.mapping.Collection)42 PersistentClass (org.hibernate.mapping.PersistentClass)19 Test (org.junit.Test)15 Property (org.hibernate.mapping.Property)11 Metadata (org.hibernate.boot.Metadata)9 MetadataSources (org.hibernate.boot.MetadataSources)9 Column (org.hibernate.mapping.Column)9 Iterator (java.util.Iterator)7 Component (org.hibernate.mapping.Component)7 RootClass (org.hibernate.mapping.RootClass)6 AnnotationException (org.hibernate.AnnotationException)5 SimpleValue (org.hibernate.mapping.SimpleValue)5 TestForIssue (org.hibernate.testing.TestForIssue)5 List (java.util.List)4 Map (java.util.Map)4 ElementCollection (javax.persistence.ElementCollection)4 StandardServiceRegistry (org.hibernate.boot.registry.StandardServiceRegistry)4 StandardServiceRegistryBuilder (org.hibernate.boot.registry.StandardServiceRegistryBuilder)4 Value (org.hibernate.mapping.Value)4 ArrayList (java.util.ArrayList)3