Search in sources :

Example 1 with ManyToMany

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

the class AnnotationBinder method bindCollection.

private static void bindCollection(PropertyHolder propertyHolder, Nullability nullability, PropertyData inferredData, Map<String, IdentifierGeneratorDefinition> classGenerators, EntityBinder entityBinder, boolean isIdentifierMapper, MetadataBuildingContext context, Map<XClass, InheritanceState> inheritanceStatePerClass, XProperty property, AnnotatedJoinColumn[] joinColumns) {
    OneToMany oneToManyAnn = property.getAnnotation(OneToMany.class);
    ManyToMany manyToManyAnn = property.getAnnotation(ManyToMany.class);
    ElementCollection elementCollectionAnn = property.getAnnotation(ElementCollection.class);
    if ((oneToManyAnn != null || manyToManyAnn != null || elementCollectionAnn != null) && isToManyAssociationWithinEmbeddableCollection(propertyHolder)) {
        throw new AnnotationException("@OneToMany, @ManyToMany or @ElementCollection cannot be used inside an @Embeddable that is also contained within an @ElementCollection: " + BinderHelper.getPath(propertyHolder, inferredData));
    }
    if (property.isAnnotationPresent(OrderColumn.class) && manyToManyAnn != null && !manyToManyAnn.mappedBy().isEmpty()) {
        throw new AnnotationException("Explicit @OrderColumn on inverse side of @ManyToMany is illegal: " + BinderHelper.getPath(propertyHolder, inferredData));
    }
    final IndexColumn indexColumn = IndexColumn.fromAnnotations(property.getAnnotation(OrderColumn.class), property.getAnnotation(org.hibernate.annotations.IndexColumn.class), property.getAnnotation(ListIndexBase.class), propertyHolder, inferredData, entityBinder.getSecondaryTables(), context);
    CollectionBinder collectionBinder = getCollectionBinder(property, hasMapKeyAnnotation(property), context);
    collectionBinder.setIndexColumn(indexColumn);
    collectionBinder.setMapKey(property.getAnnotation(MapKey.class));
    collectionBinder.setPropertyName(inferredData.getPropertyName());
    collectionBinder.setBatchSize(property.getAnnotation(BatchSize.class));
    collectionBinder.setJpaOrderBy(property.getAnnotation(jakarta.persistence.OrderBy.class));
    collectionBinder.setSqlOrderBy(getOverridableAnnotation(property, OrderBy.class, context));
    collectionBinder.setNaturalSort(property.getAnnotation(SortNatural.class));
    collectionBinder.setComparatorSort(property.getAnnotation(SortComparator.class));
    collectionBinder.setCache(property.getAnnotation(Cache.class));
    collectionBinder.setPropertyHolder(propertyHolder);
    Cascade hibernateCascade = property.getAnnotation(Cascade.class);
    NotFound notFound = property.getAnnotation(NotFound.class);
    collectionBinder.setIgnoreNotFound(notFound != null && notFound.action() == NotFoundAction.IGNORE);
    collectionBinder.setCollectionType(inferredData.getProperty().getElementClass());
    collectionBinder.setAccessType(inferredData.getDefaultAccess());
    AnnotatedColumn[] elementColumns;
    // do not use "element" if you are a JPA 2 @ElementCollection, only for legacy Hibernate mappings
    PropertyData virtualProperty = property.isAnnotationPresent(ElementCollection.class) ? inferredData : new WrappedInferredData(inferredData, "element");
    Comment comment = property.getAnnotation(Comment.class);
    if (property.isAnnotationPresent(Column.class)) {
        elementColumns = buildColumnFromAnnotation(property.getAnnotation(Column.class), comment, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
    } else if (property.isAnnotationPresent(Formula.class)) {
        elementColumns = buildFormulaFromAnnotation(getOverridableAnnotation(property, Formula.class, context), comment, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
    } else if (property.isAnnotationPresent(Columns.class)) {
        elementColumns = buildColumnsFromAnnotations(property.getAnnotation(Columns.class).columns(), comment, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
    } else {
        elementColumns = buildColumnFromNoAnnotation(comment, nullability, propertyHolder, virtualProperty, entityBinder.getSecondaryTables(), context);
    }
    JoinColumn[] joinKeyColumns = mapKeyColumns(propertyHolder, inferredData, entityBinder, context, property, collectionBinder, comment);
    AnnotatedJoinColumn[] mapJoinColumns = buildJoinColumnsWithDefaultColumnSuffix(joinKeyColumns, comment, null, entityBinder.getSecondaryTables(), propertyHolder, inferredData.getPropertyName(), "_KEY", context);
    collectionBinder.setMapKeyManyToManyColumns(mapJoinColumns);
    // potential element
    collectionBinder.setEmbedded(property.isAnnotationPresent(Embedded.class));
    collectionBinder.setElementColumns(elementColumns);
    collectionBinder.setProperty(property);
    // TODO enhance exception with @ManyToAny and @CollectionOfElements
    if (oneToManyAnn != null && manyToManyAnn != null) {
        throw new AnnotationException("@OneToMany and @ManyToMany on the same property is not allowed: " + propertyHolder.getEntityName() + "." + inferredData.getPropertyName());
    }
    String mappedBy = null;
    ReflectionManager reflectionManager = context.getBootstrapContext().getReflectionManager();
    if (oneToManyAnn != null) {
        for (AnnotatedJoinColumn column : joinColumns) {
            if (column.isSecondary()) {
                throw new NotYetImplementedException("Collections having FK in secondary table");
            }
        }
        collectionBinder.setFkJoinColumns(joinColumns);
        mappedBy = oneToManyAnn.mappedBy();
        // noinspection unchecked
        collectionBinder.setTargetEntity(reflectionManager.toXClass(oneToManyAnn.targetEntity()));
        collectionBinder.setCascadeStrategy(getCascadeStrategy(oneToManyAnn.cascade(), hibernateCascade, oneToManyAnn.orphanRemoval(), false));
        collectionBinder.setOneToMany(true);
    } else if (elementCollectionAnn != null) {
        for (AnnotatedJoinColumn column : joinColumns) {
            if (column.isSecondary()) {
                throw new NotYetImplementedException("Collections having FK in secondary table");
            }
        }
        collectionBinder.setFkJoinColumns(joinColumns);
        mappedBy = "";
        final Class<?> targetElement = elementCollectionAnn.targetClass();
        collectionBinder.setTargetEntity(reflectionManager.toXClass(targetElement));
        // collectionBinder.setCascadeStrategy( getCascadeStrategy( embeddedCollectionAnn.cascade(), hibernateCascade ) );
        collectionBinder.setOneToMany(true);
    } else if (manyToManyAnn != null) {
        mappedBy = manyToManyAnn.mappedBy();
        // noinspection unchecked
        collectionBinder.setTargetEntity(reflectionManager.toXClass(manyToManyAnn.targetEntity()));
        collectionBinder.setCascadeStrategy(getCascadeStrategy(manyToManyAnn.cascade(), hibernateCascade, false, false));
        collectionBinder.setOneToMany(false);
    } else if (property.isAnnotationPresent(ManyToAny.class)) {
        mappedBy = "";
        collectionBinder.setTargetEntity(reflectionManager.toXClass(void.class));
        collectionBinder.setCascadeStrategy(getCascadeStrategy(null, hibernateCascade, false, false));
        collectionBinder.setOneToMany(false);
    }
    collectionBinder.setMappedBy(mappedBy);
    bindJoinedTableAssociation(property, context, entityBinder, collectionBinder, propertyHolder, inferredData, mappedBy);
    OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
    boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE == onDeleteAnn.action();
    collectionBinder.setCascadeDeleteEnabled(onDeleteCascade);
    if (isIdentifierMapper) {
        collectionBinder.setInsertable(false);
        collectionBinder.setUpdatable(false);
    }
    if (property.isAnnotationPresent(CollectionId.class)) {
        // do not compute the generators unless necessary
        HashMap<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
        localGenerators.putAll(buildGenerators(property, context));
        collectionBinder.setLocalGenerators(localGenerators);
    }
    collectionBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
    collectionBinder.setDeclaringClass(inferredData.getDeclaringClass());
    collectionBinder.bind();
}
Also used : HashMap(java.util.HashMap) SortNatural(org.hibernate.annotations.SortNatural) ManyToAny(org.hibernate.annotations.ManyToAny) Formula(org.hibernate.annotations.Formula) DiscriminatorFormula(org.hibernate.annotations.DiscriminatorFormula) MapKeyJoinColumn(jakarta.persistence.MapKeyJoinColumn) JoinColumn(jakarta.persistence.JoinColumn) PrimaryKeyJoinColumn(jakarta.persistence.PrimaryKeyJoinColumn) AnnotationException(org.hibernate.AnnotationException) SortComparator(org.hibernate.annotations.SortComparator) ElementCollection(jakarta.persistence.ElementCollection) Embedded(jakarta.persistence.Embedded) Cascade(org.hibernate.annotations.Cascade) OrderBy(org.hibernate.annotations.OrderBy) BatchSize(org.hibernate.annotations.BatchSize) Comment(org.hibernate.annotations.Comment) ReflectionManager(org.hibernate.annotations.common.reflection.ReflectionManager) OrderColumn(jakarta.persistence.OrderColumn) ManyToMany(jakarta.persistence.ManyToMany) AnnotatedJoinColumn.buildJoinTableJoinColumns(org.hibernate.cfg.AnnotatedJoinColumn.buildJoinTableJoinColumns) JoinColumns(jakarta.persistence.JoinColumns) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) Columns(org.hibernate.annotations.Columns) MapKeyJoinColumns(jakarta.persistence.MapKeyJoinColumns) ListIndexBase(org.hibernate.annotations.ListIndexBase) OneToMany(jakarta.persistence.OneToMany) MapKey(jakarta.persistence.MapKey) IdentifierGeneratorDefinition(org.hibernate.boot.model.IdentifierGeneratorDefinition) XClass(org.hibernate.annotations.common.reflection.XClass) RootClass(org.hibernate.mapping.RootClass) PersistentClass(org.hibernate.mapping.PersistentClass) IdClass(jakarta.persistence.IdClass) CollectionBinder(org.hibernate.cfg.annotations.CollectionBinder) CollectionBinder.getCollectionBinder(org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder) Cache(org.hibernate.annotations.Cache) NotFound(org.hibernate.annotations.NotFound) OnDelete(org.hibernate.annotations.OnDelete)

Example 2 with ManyToMany

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

the class JPAXMLOverriddenAnnotationReader method getManyToMany.

/**
 * @see #getOneToOne(List, XMLContext.Default)
 * @see #getElementCollection(List, XMLContext.Default)
 */
private void getManyToMany(List<Annotation> annotationList, XMLContext.Default defaults) {
    Class<ManyToMany> annotationType = ManyToMany.class;
    List<JaxbManyToMany> elements = elementsForProperty.getManyToMany();
    for (JaxbManyToMany element : elements) {
        AnnotationDescriptor ad = new AnnotationDescriptor(annotationType);
        addTargetClass(element.getTargetEntity(), ad, "target-entity", defaults);
        getFetchType(ad, element.getFetch());
        getCascades(ad, element.getCascade(), defaults);
        getJoinTable(annotationList, element, defaults);
        copyAttribute(ad, "mapped-by", element.getMappedBy(), false);
        annotationList.add(AnnotationFactory.create(ad));
        getOrderBy(annotationList, element.getOrderBy());
        getMapKey(annotationList, element.getMapKey());
        getMapKeyClass(annotationList, element.getMapKeyClass(), defaults);
        getMapKeyColumn(annotationList, element.getMapKeyColumn());
        getOrderColumn(annotationList, element.getOrderColumn());
        getMapKeyTemporal(annotationList, element.getMapKeyTemporal());
        getMapKeyEnumerated(annotationList, element.getMapKeyEnumerated());
        Annotation annotation = getMapKeyAttributeOverrides(element.getMapKeyAttributeOverride(), defaults);
        addIfNotNull(annotationList, annotation);
        getMapKeyJoinColumns(annotationList, element.getMapKeyJoinColumn());
        getAccessType(annotationList, element.getAccess());
    }
    afterGetAssociation(annotationType, annotationList, defaults);
}
Also used : AnnotationDescriptor(org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor) ManyToMany(jakarta.persistence.ManyToMany) JaxbManyToMany(org.hibernate.boot.jaxb.mapping.spi.JaxbManyToMany) JaxbManyToMany(org.hibernate.boot.jaxb.mapping.spi.JaxbManyToMany) Annotation(java.lang.annotation.Annotation)

Example 3 with ManyToMany

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

the class JPAXMLOverriddenAnnotationReader method overridesDefaultsInJoinTable.

private JoinTable overridesDefaultsInJoinTable(Annotation annotation, XMLContext.Default defaults) {
    // no element but might have some default or some annotation
    boolean defaultToJoinTable = !(isPhysicalAnnotationPresent(JoinColumn.class) || isPhysicalAnnotationPresent(JoinColumns.class));
    final Class<? extends Annotation> annotationClass = annotation.annotationType();
    defaultToJoinTable = defaultToJoinTable && ((annotationClass == ManyToMany.class && StringHelper.isEmpty(((ManyToMany) annotation).mappedBy())) || (annotationClass == OneToMany.class && StringHelper.isEmpty(((OneToMany) annotation).mappedBy())) || (annotationClass == ElementCollection.class));
    final Class<JoinTable> annotationType = JoinTable.class;
    if (defaultToJoinTable && (StringHelper.isNotEmpty(defaults.getCatalog()) || StringHelper.isNotEmpty(defaults.getSchema()))) {
        AnnotationDescriptor ad = new AnnotationDescriptor(annotationType);
        if (defaults.canUseJavaAnnotations()) {
            JoinTable table = getPhysicalAnnotation(annotationType);
            if (table != null) {
                ad.setValue("name", table.name());
                ad.setValue("schema", table.schema());
                ad.setValue("catalog", table.catalog());
                ad.setValue("uniqueConstraints", table.uniqueConstraints());
                ad.setValue("joinColumns", table.joinColumns());
                ad.setValue("inverseJoinColumns", table.inverseJoinColumns());
            }
        }
        if (StringHelper.isEmpty((String) ad.valueOf("schema")) && StringHelper.isNotEmpty(defaults.getSchema())) {
            ad.setValue("schema", defaults.getSchema());
        }
        if (StringHelper.isEmpty((String) ad.valueOf("catalog")) && StringHelper.isNotEmpty(defaults.getCatalog())) {
            ad.setValue("catalog", defaults.getCatalog());
        }
        return AnnotationFactory.create(ad);
    } else if (defaults.canUseJavaAnnotations()) {
        return getPhysicalAnnotation(annotationType);
    } else {
        return null;
    }
}
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) PrimaryKeyJoinColumns(jakarta.persistence.PrimaryKeyJoinColumns) MapKeyJoinColumns(jakarta.persistence.MapKeyJoinColumns) JoinColumns(jakarta.persistence.JoinColumns) ManyToMany(jakarta.persistence.ManyToMany) JaxbManyToMany(org.hibernate.boot.jaxb.mapping.spi.JaxbManyToMany) ElementCollection(jakarta.persistence.ElementCollection) JaxbElementCollection(org.hibernate.boot.jaxb.mapping.spi.JaxbElementCollection) JaxbOneToMany(org.hibernate.boot.jaxb.mapping.spi.JaxbOneToMany) OneToMany(jakarta.persistence.OneToMany) JaxbJoinTable(org.hibernate.boot.jaxb.mapping.spi.JaxbJoinTable) JoinTable(jakarta.persistence.JoinTable)

Example 4 with ManyToMany

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

the class CollectionBinder method defineFetchingStrategy.

private void defineFetchingStrategy() {
    LazyCollection lazy = property.getAnnotation(LazyCollection.class);
    Fetch fetch = property.getAnnotation(Fetch.class);
    OneToMany oneToMany = property.getAnnotation(OneToMany.class);
    ManyToMany manyToMany = property.getAnnotation(ManyToMany.class);
    ElementCollection elementCollection = property.getAnnotation(ElementCollection.class);
    ManyToAny manyToAny = property.getAnnotation(ManyToAny.class);
    FetchType fetchType;
    if (oneToMany != null) {
        fetchType = oneToMany.fetch();
    } else if (manyToMany != null) {
        fetchType = manyToMany.fetch();
    } else if (elementCollection != null) {
        fetchType = elementCollection.fetch();
    } else if (manyToAny != null) {
        fetchType = FetchType.LAZY;
    } else {
        throw new AssertionFailure("Define fetch strategy on a property not annotated with @ManyToOne nor @OneToMany nor @ElementCollection");
    }
    if (lazy != null) {
        collection.setLazy(!(lazy.value() == LazyCollectionOption.FALSE));
        collection.setExtraLazy(lazy.value() == LazyCollectionOption.EXTRA);
    } else {
        collection.setLazy(fetchType == FetchType.LAZY);
        collection.setExtraLazy(false);
    }
    if (fetch != null) {
        if (fetch.value() == org.hibernate.annotations.FetchMode.JOIN) {
            collection.setFetchMode(FetchMode.JOIN);
            collection.setLazy(false);
        } else if (fetch.value() == org.hibernate.annotations.FetchMode.SELECT) {
            collection.setFetchMode(FetchMode.SELECT);
        } else if (fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT) {
            collection.setFetchMode(FetchMode.SELECT);
            collection.setSubselectLoadable(true);
            collection.getOwner().setSubselectLoadableCollections(true);
        } else {
            throw new AssertionFailure("Unknown FetchMode: " + fetch.value());
        }
    } else {
        collection.setFetchMode(AnnotationBinder.getFetchMode(fetchType));
    }
}
Also used : Fetch(org.hibernate.annotations.Fetch) ManyToAny(org.hibernate.annotations.ManyToAny) AssertionFailure(org.hibernate.AssertionFailure) LazyCollection(org.hibernate.annotations.LazyCollection) FetchType(jakarta.persistence.FetchType) ManyToMany(jakarta.persistence.ManyToMany) ElementCollection(jakarta.persistence.ElementCollection) OneToMany(jakarta.persistence.OneToMany)

Example 5 with ManyToMany

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

the class Ejb3XmlManyToManyTest method testCascadeAllPlusMore.

/**
 * Make sure that it doesn't break the handler when {@link CascadeType#ALL}
 * is specified in addition to a default cascade-persist or individual
 * cascade settings.
 */
@Test
public void testCascadeAllPlusMore() throws Exception {
    reader = getReader(Entity2.class, "field1", "many-to-many.orm20.xml");
    assertAnnotationPresent(ManyToMany.class);
    ManyToMany relAnno = reader.getAnnotation(ManyToMany.class);
    assertEquals(6, relAnno.cascade().length);
    assertEquals(CascadeType.ALL, relAnno.cascade()[0]);
    assertEquals(CascadeType.PERSIST, relAnno.cascade()[1]);
    assertEquals(CascadeType.MERGE, relAnno.cascade()[2]);
    assertEquals(CascadeType.REMOVE, relAnno.cascade()[3]);
    assertEquals(CascadeType.REFRESH, relAnno.cascade()[4]);
    assertEquals(CascadeType.DETACH, relAnno.cascade()[5]);
}
Also used : ManyToMany(jakarta.persistence.ManyToMany) Test(org.junit.Test)

Aggregations

ManyToMany (jakarta.persistence.ManyToMany)13 OneToMany (jakarta.persistence.OneToMany)7 ElementCollection (jakarta.persistence.ElementCollection)5 Test (org.junit.Test)4 ManyToOne (jakarta.persistence.ManyToOne)3 OneToOne (jakarta.persistence.OneToOne)3 JoinColumn (jakarta.persistence.JoinColumn)2 JoinColumns (jakarta.persistence.JoinColumns)2 MapKeyJoinColumn (jakarta.persistence.MapKeyJoinColumn)2 MapKeyJoinColumns (jakarta.persistence.MapKeyJoinColumns)2 OrderColumn (jakarta.persistence.OrderColumn)2 PrimaryKeyJoinColumn (jakarta.persistence.PrimaryKeyJoinColumn)2 PrimaryKeyJoinColumns (jakarta.persistence.PrimaryKeyJoinColumns)2 LazyCollection (org.hibernate.annotations.LazyCollection)2 ManyToAny (org.hibernate.annotations.ManyToAny)2 OrderBy (org.hibernate.annotations.OrderBy)2 AnnotationDescriptor (org.hibernate.annotations.common.annotationfactory.AnnotationDescriptor)2 JaxbManyToMany (org.hibernate.boot.jaxb.mapping.spi.JaxbManyToMany)2 Embedded (jakarta.persistence.Embedded)1 FetchType (jakarta.persistence.FetchType)1