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 カスケードを正しく処理できるようになります。今、重複したオブジェクトも例外もありません。