0

am:n 関係を持つ 2 つのテーブルがあります。データベースからデータを抽出する場合、この関係は双方向である必要があるため@ManyToMany、両方のエンティティ クラスで が必要です。しかし同時に、永続化またはマージ操作を実行するときに、非所有者クラスが所有者クラスを挿入しないようにする必要があります。

たとえばGene、所有者クラスであるクラスがあり、Ontologyクラスがあります。1 つの遺伝子には多くのオントロジーがあり、1 つのオントロジーには多くの遺伝子があります。古典的な多対多の関係。遺伝子を永続化またはマージする場合、そのオントロジーも挿入したいのですが、このオントロジーの挿入によって、それにリンクされている他のすべての遺伝子が挿入されることは望ましくありません。

一方、オントロジーを挿入する場合、そのオントロジーにリンクされた遺伝子を挿入したくありません。

私は多くの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;

すべてのカスケード タイプを試しましたが、カスケード オプションがなくても試しました。結果は同じです。

このコードを実行すると、このエラーが発生します

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)

解決済み

問題を解決しました。特殊なカスケードを処理するコントローラー クラスを作成します。

オントロジー コントローラー クラスの 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 に答える