Search in sources :

Example 31 with AnnotationException

use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.

the class Ejb3Column method initMappingColumn.

protected void initMappingColumn(String columnName, String propertyName, int length, int precision, int scale, boolean nullable, String sqlType, boolean unique, boolean applyNamingStrategy) {
    if (StringHelper.isNotEmpty(formulaString)) {
        this.formula = new Formula();
        this.formula.setFormula(formulaString);
    } else {
        this.mappingColumn = new Column();
        redefineColumnName(columnName, propertyName, applyNamingStrategy);
        this.mappingColumn.setLength(length);
        if (precision > 0) {
            // revelent precision
            this.mappingColumn.setPrecision(precision);
            this.mappingColumn.setScale(scale);
        }
        this.mappingColumn.setNullable(nullable);
        this.mappingColumn.setSqlType(sqlType);
        this.mappingColumn.setUnique(unique);
        if (writeExpression != null && !writeExpression.matches("[^?]*\\?[^?]*")) {
            throw new AnnotationException("@WriteExpression must contain exactly one value placeholder ('?') character: property [" + propertyName + "] and column [" + logicalColumnName + "]");
        }
        if (readExpression != null) {
            this.mappingColumn.setCustomRead(readExpression);
        }
        if (writeExpression != null) {
            this.mappingColumn.setCustomWrite(writeExpression);
        }
    }
}
Also used : Formula(org.hibernate.mapping.Formula) Column(org.hibernate.mapping.Column) AnnotationException(org.hibernate.AnnotationException)

Example 32 with AnnotationException

use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.

the class Ejb3JoinColumn method buildDefaultColumnName.

private String buildDefaultColumnName(final PersistentClass referencedEntity, final String logicalReferencedColumn) {
    final Database database = getBuildingContext().getMetadataCollector().getDatabase();
    final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy();
    final PhysicalNamingStrategy physicalNamingStrategy = getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy();
    Identifier columnIdentifier;
    boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null;
    boolean ownerSide = getPropertyName() != null;
    Boolean isRefColumnQuoted = StringHelper.isQuoted(logicalReferencedColumn);
    final String unquotedLogicalReferenceColumn = isRefColumnQuoted ? StringHelper.unquote(logicalReferencedColumn) : logicalReferencedColumn;
    if (mappedBySide) {
        // NOTE : While it is completely misleading here to allow for the combination
        // of a "JPA ElementCollection" to be mappedBy, the code that uses this
        // class relies on this behavior for handling the inverse side of
        // many-to-many mappings
        final AttributePath attributePath = AttributePath.parse(mappedByPropertyName);
        final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
        if (getPropertyHolder().isEntity()) {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
        } else if (JPA2ElementCollection) {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
        } else {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
        }
        columnIdentifier = implicitNamingStrategy.determineJoinColumnName(new ImplicitJoinColumnNameSource() {

            private final EntityNaming entityNaming = new EntityNaming() {

                @Override
                public String getClassName() {
                    return referencedEntity.getClassName();
                }

                @Override
                public String getEntityName() {
                    return referencedEntity.getEntityName();
                }

                @Override
                public String getJpaEntityName() {
                    return referencedEntity.getJpaEntityName();
                }
            };

            private final Identifier referencedTableName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(mappedByTableName);

            @Override
            public Nature getNature() {
                return implicitNamingNature;
            }

            @Override
            public EntityNaming getEntityNaming() {
                return entityNaming;
            }

            @Override
            public AttributePath getAttributePath() {
                return attributePath;
            }

            @Override
            public Identifier getReferencedTableName() {
                return referencedTableName;
            }

            @Override
            public Identifier getReferencedColumnName() {
                if (logicalReferencedColumn != null) {
                    return getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalReferencedColumn);
                }
                if (mappedByEntityName == null || mappedByPropertyName == null) {
                    return null;
                }
                final PersistentClass mappedByEntityBinding = getBuildingContext().getMetadataCollector().getEntityBinding(mappedByEntityName);
                final Property mappedByProperty = mappedByEntityBinding.getProperty(mappedByPropertyName);
                final SimpleValue value = (SimpleValue) mappedByProperty.getValue();
                final Iterator<Selectable> selectableValues = value.getColumnIterator();
                if (!selectableValues.hasNext()) {
                    throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (no columns)", mappedByPropertyName, propertyHolder.getPath()));
                }
                final Selectable selectable = selectableValues.next();
                if (!Column.class.isInstance(selectable)) {
                    throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (formula)", mappedByPropertyName, propertyHolder.getPath()));
                }
                if (selectableValues.hasNext()) {
                    throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (multiple columns)", mappedByPropertyName, propertyHolder.getPath()));
                }
                return getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(((Column) selectable).getQuotedName());
            }

            @Override
            public MetadataBuildingContext getBuildingContext() {
                return Ejb3JoinColumn.this.getBuildingContext();
            }
        });
        // one element was quoted so we quote
        if (isRefColumnQuoted || StringHelper.isQuoted(mappedByTableName)) {
            columnIdentifier = Identifier.quote(columnIdentifier);
        }
    } else if (ownerSide) {
        final String logicalTableName = getBuildingContext().getMetadataCollector().getLogicalTableName(referencedEntity.getTable());
        final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
        if (JPA2ElementCollection) {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
        } else if (getPropertyHolder().isEntity()) {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
        } else {
            implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
        }
        columnIdentifier = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy().determineJoinColumnName(new ImplicitJoinColumnNameSource() {

            private final EntityNaming entityNaming = new EntityNaming() {

                @Override
                public String getClassName() {
                    return referencedEntity.getClassName();
                }

                @Override
                public String getEntityName() {
                    return referencedEntity.getEntityName();
                }

                @Override
                public String getJpaEntityName() {
                    return referencedEntity.getJpaEntityName();
                }
            };

            private final AttributePath attributePath = AttributePath.parse(getPropertyName());

            private final Identifier referencedTableName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalTableName);

            private final Identifier referencedColumnName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalReferencedColumn);

            @Override
            public Nature getNature() {
                return implicitNamingNature;
            }

            @Override
            public EntityNaming getEntityNaming() {
                return entityNaming;
            }

            @Override
            public AttributePath getAttributePath() {
                return attributePath;
            }

            @Override
            public Identifier getReferencedTableName() {
                return referencedTableName;
            }

            @Override
            public Identifier getReferencedColumnName() {
                return referencedColumnName;
            }

            @Override
            public MetadataBuildingContext getBuildingContext() {
                return Ejb3JoinColumn.this.getBuildingContext();
            }
        });
        // HHH-11826 magic. See Ejb3Column and the HHH-6005 comments
        if (columnIdentifier.getText().contains("_collection&&element_")) {
            columnIdentifier = Identifier.toIdentifier(columnIdentifier.getText().replace("_collection&&element_", "_"), columnIdentifier.isQuoted());
        }
        // one element was quoted so we quote
        if (isRefColumnQuoted || StringHelper.isQuoted(logicalTableName)) {
            columnIdentifier = Identifier.quote(columnIdentifier);
        }
    } else {
        final Identifier logicalTableName = database.toIdentifier(getBuildingContext().getMetadataCollector().getLogicalTableName(referencedEntity.getTable()));
        // is an intra-entity hierarchy table join so copy the name by default
        columnIdentifier = implicitNamingStrategy.determinePrimaryKeyJoinColumnName(new ImplicitPrimaryKeyJoinColumnNameSource() {

            @Override
            public MetadataBuildingContext getBuildingContext() {
                return Ejb3JoinColumn.this.getBuildingContext();
            }

            @Override
            public Identifier getReferencedTableName() {
                return logicalTableName;
            }

            @Override
            public Identifier getReferencedPrimaryKeyColumnName() {
                return database.toIdentifier(logicalReferencedColumn);
            }
        });
        if (!columnIdentifier.isQuoted() && (isRefColumnQuoted || logicalTableName.isQuoted())) {
            columnIdentifier = Identifier.quote(columnIdentifier);
        }
    }
    return physicalNamingStrategy.toPhysicalColumnName(columnIdentifier, database.getJdbcEnvironment()).render(database.getJdbcEnvironment().getDialect());
}
Also used : ImplicitNamingStrategy(org.hibernate.boot.model.naming.ImplicitNamingStrategy) ImplicitJoinColumnNameSource(org.hibernate.boot.model.naming.ImplicitJoinColumnNameSource) ImplicitPrimaryKeyJoinColumnNameSource(org.hibernate.boot.model.naming.ImplicitPrimaryKeyJoinColumnNameSource) MetadataBuildingContext(org.hibernate.boot.spi.MetadataBuildingContext) PhysicalNamingStrategy(org.hibernate.boot.model.naming.PhysicalNamingStrategy) SimpleValue(org.hibernate.mapping.SimpleValue) Identifier(org.hibernate.boot.model.naming.Identifier) Selectable(org.hibernate.mapping.Selectable) JoinColumn(javax.persistence.JoinColumn) Column(org.hibernate.mapping.Column) PrimaryKeyJoinColumn(javax.persistence.PrimaryKeyJoinColumn) EntityNaming(org.hibernate.boot.model.naming.EntityNaming) Database(org.hibernate.boot.model.relational.Database) AnnotationException(org.hibernate.AnnotationException) Property(org.hibernate.mapping.Property) AttributePath(org.hibernate.boot.model.source.spi.AttributePath) PersistentClass(org.hibernate.mapping.PersistentClass)

Example 33 with AnnotationException

use of org.hibernate.AnnotationException 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(), 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(), 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(), 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());
    }
}
Also used : HSQLDialect(org.hibernate.dialect.HSQLDialect) AssertionFailure(org.hibernate.AssertionFailure) DependantValue(org.hibernate.mapping.DependantValue) OneToMany(org.hibernate.mapping.OneToMany) ManyToOne(org.hibernate.mapping.ManyToOne) SimpleValue(org.hibernate.mapping.SimpleValue) Formula(org.hibernate.mapping.Formula) Random(java.util.Random) Selectable(org.hibernate.mapping.Selectable) Ejb3Column(org.hibernate.cfg.Ejb3Column) MapKeyColumn(javax.persistence.MapKeyColumn) MapKeyJoinColumn(javax.persistence.MapKeyJoinColumn) Column(org.hibernate.mapping.Column) Ejb3JoinColumn(org.hibernate.cfg.Ejb3JoinColumn) SimpleValue(org.hibernate.mapping.SimpleValue) DependantValue(org.hibernate.mapping.DependantValue) Value(org.hibernate.mapping.Value) ToOne(org.hibernate.mapping.ToOne) ManyToOne(org.hibernate.mapping.ManyToOne) Iterator(java.util.Iterator) AnnotationException(org.hibernate.AnnotationException) Component(org.hibernate.mapping.Component) Property(org.hibernate.mapping.Property) XProperty(org.hibernate.annotations.common.reflection.XProperty)

Example 34 with AnnotationException

use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.

the class MapBinder method bindKeyFromAssociationTable.

private void bindKeyFromAssociationTable(XClass collType, Map persistentClasses, String mapKeyPropertyName, XProperty property, boolean isEmbedded, MetadataBuildingContext buildingContext, Ejb3Column[] mapKeyColumns, Ejb3JoinColumn[] mapKeyManyToManyColumns, String targetPropertyName) {
    if (mapKeyPropertyName != null) {
        // this is an EJB3 @MapKey
        PersistentClass associatedClass = (PersistentClass) persistentClasses.get(collType.getName());
        if (associatedClass == null)
            throw new AnnotationException("Associated class not found: " + collType);
        Property mapProperty = BinderHelper.findPropertyByName(associatedClass, mapKeyPropertyName);
        if (mapProperty == null) {
            throw new AnnotationException("Map key property not found: " + collType + "." + mapKeyPropertyName);
        }
        org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
        // HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
        InheritanceState inheritanceState = inheritanceStatePerClass.get(collType);
        PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals(inheritanceState.getType()) ? mapProperty.getPersistentClass() : associatedClass;
        Value indexValue = createFormulatedValue(mapProperty.getValue(), map, targetPropertyName, associatedClass, targetPropertyPersistentClass, buildingContext);
        map.setIndex(indexValue);
    } else {
        // this is a true Map mapping
        // TODO ugly copy/pastle from CollectionBinder.bindManyToManySecondPass
        String mapKeyType;
        Class target = void.class;
        /*
			 * target has priority over reflection for the map key type
			 * JPA 2 has priority
			 */
        if (property.isAnnotationPresent(MapKeyClass.class)) {
            target = property.getAnnotation(MapKeyClass.class).value();
        }
        if (!void.class.equals(target)) {
            mapKeyType = target.getName();
        } else {
            mapKeyType = property.getMapKey().getName();
        }
        PersistentClass collectionEntity = (PersistentClass) persistentClasses.get(mapKeyType);
        boolean isIndexOfEntities = collectionEntity != null;
        ManyToOne element = null;
        org.hibernate.mapping.Map mapValue = (org.hibernate.mapping.Map) this.collection;
        if (isIndexOfEntities) {
            element = new ManyToOne(buildingContext, mapValue.getCollectionTable());
            mapValue.setIndex(element);
            element.setReferencedEntityName(mapKeyType);
            // element.setFetchMode( fetchMode );
            // element.setLazy( fetchMode != FetchMode.JOIN );
            // make the second join non lazy
            element.setFetchMode(FetchMode.JOIN);
            element.setLazy(false);
        // does not make sense for a map key element.setIgnoreNotFound( ignoreNotFound );
        } else {
            XClass keyXClass;
            AnnotatedClassType classType;
            if (BinderHelper.PRIMITIVE_NAMES.contains(mapKeyType)) {
                classType = AnnotatedClassType.NONE;
                keyXClass = null;
            } else {
                try {
                    keyXClass = buildingContext.getBootstrapContext().getReflectionManager().classForName(mapKeyType);
                } catch (ClassLoadingException e) {
                    throw new AnnotationException("Unable to find class: " + mapKeyType, e);
                }
                classType = buildingContext.getMetadataCollector().getClassType(keyXClass);
                // force in case of attribute override naming the key
                if (isEmbedded || mappingDefinedAttributeOverrideOnMapKey(property)) {
                    classType = AnnotatedClassType.EMBEDDABLE;
                }
            }
            CollectionPropertyHolder holder = PropertyHolderBuilder.buildPropertyHolder(mapValue, StringHelper.qualify(mapValue.getRole(), "mapkey"), keyXClass, property, propertyHolder, buildingContext);
            // 'propertyHolder' is the PropertyHolder for the owner of the collection
            // 'holder' is the CollectionPropertyHolder.
            // 'property' is the collection XProperty
            propertyHolder.startingProperty(property);
            holder.prepare(property);
            PersistentClass owner = mapValue.getOwner();
            AccessType accessType;
            // String accessType = access != null ? access.value() : null;
            if (owner.getIdentifierProperty() != null) {
                accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
            } else if (owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0) {
                Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
                accessType = prop.getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
            } else {
                throw new AssertionFailure("Unable to guess collection property accessor name");
            }
            if (AnnotatedClassType.EMBEDDABLE.equals(classType)) {
                EntityBinder entityBinder = new EntityBinder();
                PropertyData inferredData;
                if (isHibernateExtensionMapping()) {
                    inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "index", keyXClass);
                } else {
                    // "key" is the JPA 2 prefix for map keys
                    inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "key", keyXClass);
                }
                // TODO be smart with isNullable
                Component component = AnnotationBinder.fillComponent(holder, inferredData, accessType, true, entityBinder, false, false, true, buildingContext, inheritanceStatePerClass);
                mapValue.setIndex(component);
            } else {
                SimpleValueBinder elementBinder = new SimpleValueBinder();
                elementBinder.setBuildingContext(buildingContext);
                elementBinder.setReturnedClassName(mapKeyType);
                Ejb3Column[] elementColumns = mapKeyColumns;
                if (elementColumns == null || elementColumns.length == 0) {
                    elementColumns = new Ejb3Column[1];
                    Ejb3Column column = new Ejb3Column();
                    column.setImplicit(false);
                    column.setNullable(true);
                    column.setLength(Ejb3Column.DEFAULT_COLUMN_LENGTH);
                    column.setLogicalColumnName(Collection.DEFAULT_KEY_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(mapValue.getCollectionTable());
                }
                elementBinder.setColumns(elementColumns);
                // do not call setType as it extract the type from @Type
                // the algorithm generally does not apply for map key anyway
                elementBinder.setKey(true);
                elementBinder.setType(property, keyXClass, this.collection.getOwnerEntityName(), holder.mapKeyAttributeConverterDescriptor(property, keyXClass));
                elementBinder.setPersistentClassName(propertyHolder.getEntityName());
                elementBinder.setAccessType(accessType);
                mapValue.setIndex(elementBinder.make());
            }
        }
        // FIXME pass the Index Entity JoinColumns
        if (!collection.isOneToMany()) {
            // index column shoud not be null
            for (Ejb3JoinColumn col : mapKeyManyToManyColumns) {
                col.forceNotNull();
            }
        }
        if (element != null) {
            final javax.persistence.ForeignKey foreignKey = getMapKeyForeignKey(property);
            if (foreignKey != null) {
                if (foreignKey.value() == ConstraintMode.NO_CONSTRAINT) {
                    element.setForeignKeyName("none");
                } else {
                    element.setForeignKeyName(StringHelper.nullIfEmpty(foreignKey.name()));
                    element.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKey.foreignKeyDefinition()));
                }
            }
        }
        if (isIndexOfEntities) {
            bindManytoManyInverseFk(collectionEntity, mapKeyManyToManyColumns, element, // a map key column has no unique constraint
            false, buildingContext);
        }
    }
}
Also used : PropertyData(org.hibernate.cfg.PropertyData) PropertyPreloadedData(org.hibernate.cfg.PropertyPreloadedData) XClass(org.hibernate.annotations.common.reflection.XClass) ManyToOne(org.hibernate.mapping.ManyToOne) 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) AccessType(org.hibernate.cfg.AccessType) PersistentClass(org.hibernate.mapping.PersistentClass) CollectionPropertyHolder(org.hibernate.cfg.CollectionPropertyHolder) AssertionFailure(org.hibernate.AssertionFailure) ClassLoadingException(org.hibernate.annotations.common.reflection.ClassLoadingException) Join(org.hibernate.mapping.Join) InheritanceState(org.hibernate.cfg.InheritanceState) SimpleValue(org.hibernate.mapping.SimpleValue) DependantValue(org.hibernate.mapping.DependantValue) Value(org.hibernate.mapping.Value) MapKeyClass(javax.persistence.MapKeyClass) PersistentClass(org.hibernate.mapping.PersistentClass) XClass(org.hibernate.annotations.common.reflection.XClass) Ejb3JoinColumn(org.hibernate.cfg.Ejb3JoinColumn) Map(java.util.Map) HashMap(java.util.HashMap) AnnotatedClassType(org.hibernate.cfg.AnnotatedClassType)

Example 35 with AnnotationException

use of org.hibernate.AnnotationException 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);
    }
}
Also used : AssertionFailure(org.hibernate.AssertionFailure) SyntheticProperty(org.hibernate.mapping.SyntheticProperty) Join(org.hibernate.mapping.Join) UniqueConstraint(javax.persistence.UniqueConstraint) 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) XProperty(org.hibernate.annotations.common.reflection.XProperty) PersistentClass(org.hibernate.mapping.PersistentClass)

Aggregations

AnnotationException (org.hibernate.AnnotationException)85 AnnotationDescriptor (org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor)15 PersistentClass (org.hibernate.mapping.PersistentClass)14 AnnotatedElement (java.lang.reflect.AnnotatedElement)12 Element (org.dom4j.Element)12 XClass (org.hibernate.annotations.common.reflection.XClass)12 HashMap (java.util.HashMap)11 MappingException (org.hibernate.MappingException)11 XProperty (org.hibernate.annotations.common.reflection.XProperty)11 Property (org.hibernate.mapping.Property)11 SimpleValue (org.hibernate.mapping.SimpleValue)11 Test (org.junit.Test)10 AssertionFailure (org.hibernate.AssertionFailure)9 ArrayList (java.util.ArrayList)8 ClassLoadingException (org.hibernate.boot.registry.classloading.spi.ClassLoadingException)8 Column (org.hibernate.mapping.Column)8 IdClass (javax.persistence.IdClass)7 MapKeyClass (javax.persistence.MapKeyClass)7 Component (org.hibernate.mapping.Component)7 Properties (java.util.Properties)6