0

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

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

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

我一直在尝试使用很多 JPA 标签,但@ManyToMany没有任何东西可以按照我想要的方式工作。

有没有人有解决这个问题的想法?

基因类

@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;

本体类

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

我尝试了所有 Cascade 类型,甚至没有使用 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 级联。现在,我没有任何重复的对象,也没有例外。

4

3 回答 3

1

这些基因从何而来?

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

如果您不想再持久化,则不要将它们添加到基因集合中。

于 2012-08-30T13:40:24.143 回答
0

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

于 2012-08-29T10:54:08.283 回答
0

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

见, http ://en.wikibooks.org/wiki/Java_Persistence/ManyToMany#Bi-directional_Many_to_Many

于 2012-08-29T12:37:32.023 回答