如何避免ManyToMany关系上的双向插入

时间:2012-08-29 09:31:21

标签: java jpa many-to-many

我有两个m:n关系的表。当我从数据库中提取数据时,这种关系应该是双向的,因此,我需要两个实体类中的@ManyToMany。但是,与此同时,我需要非owner类在我对其执行持久化或合并操作时不插入所有者类。

例如,我有Gene类,即所有者类,我有Ontology类。 One Gene有许多Ontology,一个Ontology有很多基因。经典的多对多关系。如果我坚持或合并基因我也想插入它的Ontologies,但我不希望这个Ontology插入插入所有其他链接到它的基因。

另一方面,如果我插入一个Ontology,我不想插入与该Ontology相关的基因。

我一直在试用@ManyToMany上的很多JPA标签,但没有任何方法可以按照我想要的方式进行。

有任何一个想法可以解决这个问题吗?

基因类

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = GeneTables.GENEINFO_HAS_ONTOLOGY,
joinColumns =
@JoinColumn(name = "GeneInfo_WID", referencedColumnName = "WID"),
inverseJoinColumns =
@JoinColumn(name = "Ontology_WID", referencedColumnName = "WID"))
private Set<Ontology> ontology;

Ontology类

@ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "ontology")
private Set<GeneInfo> geneInfo;

我尝试了所有Cascade类型,甚至没有级联选项。结果是一样的。

执行此代码时出现此错误

EntityManager em = getEntityManager();
m.getTransaction().begin();
em.persist(ontology);
em.getTransaction().commit();

我有这个错误:

[EL Warning]: 2012-08-29 14:52:13.013--UnitOfWork(544628019)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST 

at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)

at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)

at org.jbiowh.core.datasets.ontology.controller.OntologyJpaController.create(OntologyJpaController.java:41)

at org.jbiowh.tools.prototypes.Test.main(Test.java:65)

解决了

我解决了这个问题。我创建了控制器类来处理特殊的级联。

Ontology控制器类上的create方法将是:

if (loadGeneFlag && ontology.getGene() != null && !ontology.getGene().isEmpty()) {
    Set<Gene> geneSet = new HashSet<>();
    GeneJpaController gController = new GeneJpaController(emf);
    for (Gene gene : ontology.getGene()) {
        Gene geneOnDB = em.find(Gene.class, gene.getWid());
        if (geneOnDB != null) {
            geneSet.add(geneOnDB);
        } else {
            gController.create(gene);
            geneSet.add(em.getReference(Gene.class, gene.getWid()));
        }
    }
    ontology.setGene(geneSet);
}

此代码将使用Gene控制器类创建所有基因引用,而不是遵循级联操作。这使我有可能在Gene控制器类上正确处理Gene级联。现在,我没有任何重复的对象,也没有例外。

3 个答案:

答案 0 :(得分:1)

这些基因来自哪里?

如果它们是新的,那么你需要坚持它们,或者设置级联坚持基因关系。如果它们存在,那么您需要在当前EntityManager /事务的上下文中找到它们。

如果你不想那么坚持,那就不要把它们添加到基因集合中。

答案 1 :(得分:0)

在两个实体上设置 cascade = CascadeType.REFRESH 或删除两个实体上的级联属性。

答案 2 :(得分:0)

您必须在双向关系的一侧使用mappedBy。

请参阅, http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany#Bi-directional_Many_to_Many