Search in sources :

Example 16 with JoinColumn

use of jakarta.persistence.JoinColumn in project hibernate-orm by hibernate.

the class JPAXMLOverriddenAnnotationReader method getJoinColumns.

private JoinColumn[] getJoinColumns(List<JaxbJoinColumn> subelements, boolean isInverse) {
    List<JoinColumn> joinColumns = new ArrayList<>();
    if (subelements != null) {
        for (JaxbJoinColumn subelement : subelements) {
            AnnotationDescriptor column = new AnnotationDescriptor(JoinColumn.class);
            copyAttribute(column, "name", subelement.getName(), false);
            copyAttribute(column, "referenced-column-name", subelement.getReferencedColumnName(), false);
            copyAttribute(column, "unique", subelement.isUnique(), false);
            copyAttribute(column, "nullable", subelement.isNullable(), false);
            copyAttribute(column, "insertable", subelement.isInsertable(), false);
            copyAttribute(column, "updatable", subelement.isUpdatable(), false);
            copyAttribute(column, "column-definition", subelement.getColumnDefinition(), false);
            copyAttribute(column, "table", subelement.getTable(), false);
            joinColumns.add(AnnotationFactory.create(column));
        }
    }
    return joinColumns.toArray(new JoinColumn[joinColumns.size()]);
}
Also used : AnnotationDescriptor(org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor) JaxbPrimaryKeyJoinColumn(org.hibernate.boot.jaxb.mapping.spi.JaxbPrimaryKeyJoinColumn) JaxbMapKeyJoinColumn(org.hibernate.boot.jaxb.mapping.spi.JaxbMapKeyJoinColumn) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) JaxbJoinColumn(org.hibernate.boot.jaxb.mapping.spi.JaxbJoinColumn) JaxbJoinColumn(org.hibernate.boot.jaxb.mapping.spi.JaxbJoinColumn) ArrayList(java.util.ArrayList)

Example 17 with JoinColumn

use of jakarta.persistence.JoinColumn in project hibernate-orm by hibernate.

the class AnnotationBinder method addProperty.

private static int addProperty(PropertyContainer propertyContainer, XProperty property, List<PropertyData> inFlightPropertyDataList, MetadataBuildingContext context) {
    // and if so, skip it..
    for (PropertyData propertyData : inFlightPropertyDataList) {
        if (propertyData.getPropertyName().equals(property.getName())) {
            Id incomingIdProperty = property.getAnnotation(Id.class);
            Id existingIdProperty = propertyData.getProperty().getAnnotation(Id.class);
            if (incomingIdProperty != null && existingIdProperty == null) {
                throw new MappingException(String.format("You cannot override the [%s] non-identifier property from the [%s] base class or @MappedSuperclass and make it an identifier in the [%s] subclass!", propertyData.getProperty().getName(), propertyData.getProperty().getDeclaringClass().getName(), property.getDeclaringClass().getName()));
            }
            // EARLY EXIT!!!
            return 0;
        }
    }
    final XClass declaringClass = propertyContainer.getDeclaringClass();
    final XClass entity = propertyContainer.getEntityAtStake();
    int idPropertyCounter = 0;
    PropertyData propertyAnnotatedElement = new PropertyInferredData(declaringClass, property, propertyContainer.getClassLevelAccessType().getType(), context.getBootstrapContext().getReflectionManager());
    /*
		 * put element annotated by @Id in front
		 * since it has to be parsed before any association by Hibernate
		 */
    final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
    if (hasIdAnnotation(element)) {
        inFlightPropertyDataList.add(0, propertyAnnotatedElement);
        /*
			 * The property must be put in hibernate.properties as it's a system wide property. Fixable?
			 * TODO support true/false/default on the property instead of present / not present
			 * TODO is @Column mandatory?
			 * TODO add method support
			 */
        if (context.getBuildingOptions().isSpecjProprietarySyntaxEnabled()) {
            if (element.isAnnotationPresent(Id.class) && element.isAnnotationPresent(Column.class)) {
                String columnName = element.getAnnotation(Column.class).name();
                for (XProperty prop : declaringClass.getDeclaredProperties(AccessType.FIELD.getType())) {
                    if (!prop.isAnnotationPresent(MapsId.class)) {
                        /*
							 * The detection of a configured individual JoinColumn differs between Annotation
							 * and XML configuration processing.
							 */
                        boolean isRequiredAnnotationPresent = false;
                        JoinColumns groupAnnotation = prop.getAnnotation(JoinColumns.class);
                        if ((prop.isAnnotationPresent(JoinColumn.class) && prop.getAnnotation(JoinColumn.class).name().equals(columnName))) {
                            isRequiredAnnotationPresent = true;
                        } else if (prop.isAnnotationPresent(JoinColumns.class)) {
                            for (JoinColumn columnAnnotation : groupAnnotation.value()) {
                                if (columnName.equals(columnAnnotation.name())) {
                                    isRequiredAnnotationPresent = true;
                                    break;
                                }
                            }
                        }
                        if (isRequiredAnnotationPresent) {
                            // create a PropertyData for the specJ property holding the mapping
                            PropertyData specJPropertyData = new PropertyInferredData(declaringClass, // same dec
                            prop, // the actual @XToOne property
                            propertyContainer.getClassLevelAccessType().getType(), // TODO we should get the right accessor but the same as id would do
                            context.getBootstrapContext().getReflectionManager());
                            context.getMetadataCollector().addPropertyAnnotatedWithMapsIdSpecj(entity, specJPropertyData, element.toString());
                        }
                    }
                }
            }
        }
        if (hasToOneAnnotation(element)) {
            context.getMetadataCollector().addToOneAndIdProperty(entity, propertyAnnotatedElement);
        }
        idPropertyCounter++;
    } else {
        inFlightPropertyDataList.add(propertyAnnotatedElement);
    }
    if (element.isAnnotationPresent(MapsId.class)) {
        context.getMetadataCollector().addPropertyAnnotatedWithMapsId(entity, propertyAnnotatedElement);
    }
    return idPropertyCounter;
}
Also used : BinderHelper.getPropertyOverriddenByMapperOrMapsId(org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId) MapsId(jakarta.persistence.MapsId) XProperty(org.hibernate.annotations.common.reflection.XProperty) AnnotatedJoinColumn.buildJoinTableJoinColumns(org.hibernate.cfg.AnnotatedJoinColumn.buildJoinTableJoinColumns) JoinColumns(jakarta.persistence.JoinColumns) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) MapKeyJoinColumns(jakarta.persistence.MapKeyJoinColumns) XAnnotatedElement(org.hibernate.annotations.common.reflection.XAnnotatedElement) XClass(org.hibernate.annotations.common.reflection.XClass) UniqueConstraint(jakarta.persistence.UniqueConstraint) Constraint(org.hibernate.mapping.Constraint) MappingException(org.hibernate.MappingException) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) MapKeyColumn(jakarta.persistence.MapKeyColumn) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) Column(jakarta.persistence.Column) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) OrderColumn(jakarta.persistence.OrderColumn) DiscriminatorColumn(jakarta.persistence.DiscriminatorColumn) AnnotatedDiscriminatorColumn.buildDiscriminatorColumn(org.hibernate.cfg.AnnotatedDiscriminatorColumn.buildDiscriminatorColumn) BinderHelper.getPropertyOverriddenByMapperOrMapsId(org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId) Id(jakarta.persistence.Id) NaturalId(org.hibernate.annotations.NaturalId) EmbeddedId(jakarta.persistence.EmbeddedId) MapsId(jakarta.persistence.MapsId) CollectionId(org.hibernate.annotations.CollectionId)

Example 18 with JoinColumn

use of jakarta.persistence.JoinColumn in project hibernate-orm by hibernate.

the class AnnotationBinder method bindOneToOne.

private static void bindOneToOne(PropertyHolder propertyHolder, PropertyData inferredData, boolean isIdentifierMapper, boolean inSecondPass, MetadataBuildingContext context, XProperty property, AnnotatedJoinColumn[] joinColumns, PropertyBinder propertyBinder, boolean forcePersist) {
    OneToOne ann = property.getAnnotation(OneToOne.class);
    // check validity
    if (property.isAnnotationPresent(Column.class) || property.isAnnotationPresent(Columns.class)) {
        throw new AnnotationException("@Column(s) not allowed on a @OneToOne property: " + BinderHelper.getPath(propertyHolder, inferredData));
    }
    // FIXME support a proper PKJCs
    boolean trueOneToOne = property.isAnnotationPresent(PrimaryKeyJoinColumn.class) || property.isAnnotationPresent(PrimaryKeyJoinColumns.class);
    Cascade hibernateCascade = property.getAnnotation(Cascade.class);
    NotFound notFound = property.getAnnotation(NotFound.class);
    boolean ignoreNotFound = notFound != null && notFound.action() == NotFoundAction.IGNORE;
    // MapsId means the columns belong to the pk;
    // A @MapsId association (obviously) must be non-null when the entity is first persisted.
    // If a @MapsId association is not mapped with @NotFound(IGNORE), then the association
    // is mandatory (even if the association has optional=true).
    // If a @MapsId association has optional=true and is mapped with @NotFound(IGNORE) then
    // the association is optional.
    // @OneToOne(optional = true) with @PKJC makes the association optional.
    final boolean mandatory = !ann.optional() || property.isAnnotationPresent(Id.class) || property.isAnnotationPresent(MapsId.class) && !ignoreNotFound;
    matchIgnoreNotFoundWithFetchType(propertyHolder.getEntityName(), property.getName(), ignoreNotFound, ann.fetch());
    OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
    JoinTable assocTable = propertyHolder.getJoinTable(property);
    if (assocTable != null) {
        Join join = propertyHolder.addJoin(assocTable, false);
        for (AnnotatedJoinColumn joinColumn : joinColumns) {
            joinColumn.setExplicitTableName(join.getTable().getName());
        }
    }
    bindOneToOne(getCascadeStrategy(ann.cascade(), hibernateCascade, ann.orphanRemoval(), forcePersist), joinColumns, !mandatory, getFetchMode(ann.fetch()), ignoreNotFound, onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action(), ToOneBinder.getTargetEntity(inferredData, context), propertyHolder, inferredData, ann.mappedBy(), trueOneToOne, isIdentifierMapper, inSecondPass, propertyBinder, context);
}
Also used : AnnotatedJoinColumn.buildJoinTableJoinColumns(org.hibernate.cfg.AnnotatedJoinColumn.buildJoinTableJoinColumns) JoinColumns(jakarta.persistence.JoinColumns) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) Columns(org.hibernate.annotations.Columns) MapKeyJoinColumns(jakarta.persistence.MapKeyJoinColumns) Join(org.hibernate.mapping.Join) OneToOne(jakarta.persistence.OneToOne) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) MapKeyColumn(jakarta.persistence.MapKeyColumn) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) Column(jakarta.persistence.Column) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) OrderColumn(jakarta.persistence.OrderColumn) DiscriminatorColumn(jakarta.persistence.DiscriminatorColumn) AnnotatedDiscriminatorColumn.buildDiscriminatorColumn(org.hibernate.cfg.AnnotatedDiscriminatorColumn.buildDiscriminatorColumn) AnnotationException(org.hibernate.AnnotationException) Cascade(org.hibernate.annotations.Cascade) NotFound(org.hibernate.annotations.NotFound) OnDelete(org.hibernate.annotations.OnDelete) JoinTable(jakarta.persistence.JoinTable)

Example 19 with JoinColumn

use of jakarta.persistence.JoinColumn in project hibernate-orm by hibernate.

the class AnnotationBinder method bindManyToOne.

private static void bindManyToOne(String cascadeStrategy, AnnotatedJoinColumn[] columns, boolean optional, boolean ignoreNotFound, boolean cascadeOnDelete, XClass targetEntity, PropertyHolder propertyHolder, PropertyData inferredData, boolean unique, boolean isIdentifierMapper, boolean inSecondPass, PropertyBinder propertyBinder, MetadataBuildingContext context) {
    // All FK columns should be in the same table
    org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne(context, columns[0].getTable());
    // This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne
    if (unique) {
        value.markAsLogicalOneToOne();
    }
    value.setReferencedEntityName(ToOneBinder.getReferenceEntityName(inferredData, targetEntity, context));
    final XProperty property = inferredData.getProperty();
    defineFetchingStrategy(value, property);
    // value.setFetchMode( fetchMode );
    value.setIgnoreNotFound(ignoreNotFound);
    value.setCascadeDeleteEnabled(cascadeOnDelete);
    // value.setLazy( fetchMode != FetchMode.JOIN );
    if (!optional) {
        for (AnnotatedJoinColumn column : columns) {
            column.setNullable(false);
        }
    }
    if (property.isAnnotationPresent(MapsId.class)) {
        // read only
        for (AnnotatedJoinColumn column : columns) {
            column.setInsertable(false);
            column.setUpdatable(false);
        }
    }
    final JoinColumn joinColumn = property.getAnnotation(JoinColumn.class);
    final JoinColumns joinColumns = property.getAnnotation(JoinColumns.class);
    // Make sure that JPA1 key-many-to-one columns are read only too
    boolean hasSpecjManyToOne = false;
    if (context.getBuildingOptions().isSpecjProprietarySyntaxEnabled()) {
        String columnName = "";
        for (XProperty prop : inferredData.getDeclaringClass().getDeclaredProperties(AccessType.FIELD.getType())) {
            if (prop.isAnnotationPresent(Id.class) && prop.isAnnotationPresent(Column.class)) {
                columnName = prop.getAnnotation(Column.class).name();
            }
            if (property.isAnnotationPresent(ManyToOne.class) && joinColumn != null && !BinderHelper.isEmptyAnnotationValue(joinColumn.name()) && joinColumn.name().equals(columnName) && !property.isAnnotationPresent(MapsId.class)) {
                hasSpecjManyToOne = true;
                for (AnnotatedJoinColumn column : columns) {
                    column.setInsertable(false);
                    column.setUpdatable(false);
                }
            }
        }
    }
    value.setTypeName(inferredData.getClassOrElementName());
    final String propertyName = inferredData.getPropertyName();
    value.setTypeUsingReflection(propertyHolder.getClassName(), propertyName);
    bindForeignKeyNameAndDefinition(value, property, propertyHolder.getOverriddenForeignKey(StringHelper.qualify(propertyHolder.getPath(), propertyName)), joinColumn, joinColumns, context);
    String path = propertyHolder.getPath() + "." + propertyName;
    FkSecondPass secondPass = new ToOneFkSecondPass(value, columns, // cannot have nullable and unique on certain DBs like Derby
    !optional && unique, propertyHolder.getEntityOwnerClassName(), path, context);
    if (inSecondPass) {
        secondPass.doSecondPass(context.getMetadataCollector().getEntityBindingMap());
    } else {
        context.getMetadataCollector().addSecondPass(secondPass);
    }
    AnnotatedColumn.checkPropertyConsistency(columns, propertyHolder.getEntityName() + "." + propertyName);
    // PropertyBinder binder = new PropertyBinder();
    propertyBinder.setName(propertyName);
    propertyBinder.setValue(value);
    // binder.setCascade(cascadeStrategy);
    if (isIdentifierMapper) {
        propertyBinder.setInsertable(false);
        propertyBinder.setUpdatable(false);
    } else if (hasSpecjManyToOne) {
        propertyBinder.setInsertable(false);
        propertyBinder.setUpdatable(false);
    } else {
        propertyBinder.setInsertable(columns[0].isInsertable());
        propertyBinder.setUpdatable(columns[0].isUpdatable());
    }
    propertyBinder.setColumns(columns);
    propertyBinder.setAccessType(inferredData.getDefaultAccess());
    propertyBinder.setCascade(cascadeStrategy);
    propertyBinder.setProperty(property);
    propertyBinder.setXToMany(true);
    final Property boundProperty = propertyBinder.makePropertyAndBind();
    if (joinColumn != null) {
        boundProperty.setOptional(joinColumn.nullable() && optional);
    } else {
        boundProperty.setOptional(optional);
    }
}
Also used : XProperty(org.hibernate.annotations.common.reflection.XProperty) AnnotatedJoinColumn.buildJoinTableJoinColumns(org.hibernate.cfg.AnnotatedJoinColumn.buildJoinTableJoinColumns) JoinColumns(jakarta.persistence.JoinColumns) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) MapKeyJoinColumns(jakarta.persistence.MapKeyJoinColumns) ManyToOne(jakarta.persistence.ManyToOne) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) MapKeyColumn(jakarta.persistence.MapKeyColumn) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) Column(jakarta.persistence.Column) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) OrderColumn(jakarta.persistence.OrderColumn) DiscriminatorColumn(jakarta.persistence.DiscriminatorColumn) AnnotatedDiscriminatorColumn.buildDiscriminatorColumn(org.hibernate.cfg.AnnotatedDiscriminatorColumn.buildDiscriminatorColumn) BinderHelper.getPropertyOverriddenByMapperOrMapsId(org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId) Id(jakarta.persistence.Id) NaturalId(org.hibernate.annotations.NaturalId) EmbeddedId(jakarta.persistence.EmbeddedId) MapsId(jakarta.persistence.MapsId) CollectionId(org.hibernate.annotations.CollectionId) Property(org.hibernate.mapping.Property) XProperty(org.hibernate.annotations.common.reflection.XProperty)

Example 20 with JoinColumn

use of jakarta.persistence.JoinColumn in project hibernate-orm by hibernate.

the class AnnotatedJoinColumn method buildJoinColumn.

/**
 * Build JoinColumn for a JOINED hierarchy
 */
public static AnnotatedJoinColumn buildJoinColumn(PrimaryKeyJoinColumn pkJoinAnn, JoinColumn joinAnn, Value identifier, Map<String, Join> joins, PropertyHolder propertyHolder, MetadataBuildingContext context) {
    final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
    Column col = identifier.getColumns().get(0);
    String defaultName = context.getMetadataCollector().getLogicalColumnName(identifier.getTable(), col.getQuotedName());
    if (pkJoinAnn != null || joinAnn != null) {
        String colName;
        String columnDefinition;
        String referencedColumnName;
        if (pkJoinAnn != null) {
            colName = pkJoinAnn.name();
            columnDefinition = pkJoinAnn.columnDefinition();
            referencedColumnName = pkJoinAnn.referencedColumnName();
        } else {
            colName = joinAnn.name();
            columnDefinition = joinAnn.columnDefinition();
            referencedColumnName = joinAnn.referencedColumnName();
        }
        final String sqlType;
        if (columnDefinition.isEmpty()) {
            sqlType = null;
        } else {
            sqlType = normalizer.toDatabaseIdentifierText(columnDefinition);
        }
        final String name;
        if (colName != null && colName.isEmpty()) {
            name = normalizer.normalizeIdentifierQuotingAsString(defaultName);
        } else {
            name = context.getObjectNameNormalizer().normalizeIdentifierQuotingAsString(colName);
        }
        return new AnnotatedJoinColumn(sqlType, name, null, false, false, true, true, referencedColumnName, null, joins, propertyHolder, null, null, false, context);
    } else {
        defaultName = context.getObjectNameNormalizer().normalizeIdentifierQuotingAsString(defaultName);
        return new AnnotatedJoinColumn(null, defaultName, null, false, false, true, true, null, null, joins, propertyHolder, null, null, true, context);
    }
}
Also used : PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) Column(org.hibernate.mapping.Column) JoinColumn(jakarta.persistence.JoinColumn) ObjectNameNormalizer(org.hibernate.boot.model.naming.ObjectNameNormalizer)

Aggregations

JoinColumn (jakarta.persistence.JoinColumn)28 MapKeyJoinColumn (jakarta.persistence.MapKeyJoinColumn)16 PrimaryKeyJoinColumn (jakarta.persistence.PrimaryKeyJoinColumn)16 JoinColumns (jakarta.persistence.JoinColumns)12 Test (org.junit.Test)12 JoinTable (jakarta.persistence.JoinTable)10 UniqueConstraint (jakarta.persistence.UniqueConstraint)9 MapKeyJoinColumns (jakarta.persistence.MapKeyJoinColumns)8 PrimaryKeyJoinColumns (jakarta.persistence.PrimaryKeyJoinColumns)7 OrderColumn (jakarta.persistence.OrderColumn)6 Column (jakarta.persistence.Column)5 DiscriminatorColumn (jakarta.persistence.DiscriminatorColumn)5 MapKeyColumn (jakarta.persistence.MapKeyColumn)5 AnnotationException (org.hibernate.AnnotationException)5 AnnotatedDiscriminatorColumn.buildDiscriminatorColumn (org.hibernate.cfg.AnnotatedDiscriminatorColumn.buildDiscriminatorColumn)5 AnnotatedJoinColumn.buildJoinTableJoinColumns (org.hibernate.cfg.AnnotatedJoinColumn.buildJoinTableJoinColumns)5 OnDelete (org.hibernate.annotations.OnDelete)4 CollectionTable (jakarta.persistence.CollectionTable)3 Cascade (org.hibernate.annotations.Cascade)3 Columns (org.hibernate.annotations.Columns)3