0

エンティティ間に複雑な階層があります。エラーのため (以下を参照)、多くの場所に CASCADE.ALL または CASCADE.PERSIST を配置しました。上から下まで、注釈は問題ありません。しかし、下から上まで、それは私が望むものではありません。

オブジェクトが重複して保存される原因となります。

どうすればこの問題を解決できますか??

PS C と F の関係が必要な理由: F オブジェクトを取得する標準的な方法だからです。(現在、ユースケースの %90)

JPA オブジェクト間の関係

** Java コード -- A ツリーの作成 **

   public A convertToA(final QueryAType aType, final A parent) {
        final A a = new A();

        if (parent != null) {
            a.setVater(parent);
        }

        final List<A> children = new ArrayList<A>();
        for (final QueryAType childPart : aType.getUnterbauteil()) {
            children.add(convertToA(childPart, a));
        }

        final List<B> bList = new ArrayList<B>();
        for (final QueryBType bType : aType.getBType()) {
            bList.add(convertToB(bType, a));
        }
        a.setBList(bList);
        a.setKinder(children);
        return a;
    }

    public B convertToB(final QueryBType bType, final A a) {
        final B b = new B();
        b.setA(a);

        final List<C> cList = new ArrayList<C>();
        for (final QueryCType cType : bType.getCType()) {
            cList.add(convertToC(cType, b));
        }
        b.setCList(cList);
        return b;
    }

    public C convertToC(final QueryCType cType, final B b) {
        final C c = new C();
        c.setB(b);

        final List<D> dList = new ArrayList<D>();
        for (final QueryDType dType : cType.getDType()) {
            dList.add(convertToD(dType, c));
        }
        c.setDList(dList);
        return c;
    }

    public D convertToD(final QueryDType dType, final C c) {
        final D d = new D();
        d.setProbe(c);

        final List<E> eList = new ArrayList<E>();
        for (final QueryEType eType : dType.getEType()) {
            eList.add(convertToE(eType, d, c));
        }

        d.setEList(eList);

        return d;
    }

    public E convertToE(final QueryEType eType, final D d, final C c) {
        final E e = new E();
        e.setD(d);

        final List<F> fList = new ArrayList<F>();
        for (final QueryFType fType : eType.getFType()) {
            fList.add(convertToF(fType, e, c));
        }
        e.setFList(fList);
        c.setFList(fList);
        return e;
    }

    public F convertToF(final QueryFType fType, final E e, final C c) {
        final F f = new F();
        f.setC(c);
        f.setE(e);

        final List<G> gList = new ArrayList<G>();
        for (final QueryGType gType : fType.getGType()) {
            gList.add(convertToG(gType, f));
        }
        f.setGList(gList);

        return f;
    }

    public G convertToG(final QueryGType gType, final F f) {
        final G g = new G();
        g.setMethode(f);
        return g;
    }

カスケードなしのエラー:


org.apache.openjpa.persistence.InvalidStateException: フィールド "com.xxx.yyy.data.entity.Fe を介して永続性をカスケードしているときに、管理されていないライフサイクル状態で管理されていないオブジェクト "com.xxx.yyy.data.entity.E@18e0a217" が検出されました"フラッシュ中。ただし、このフィールドではカスケードの持続は許可されません。アンマネージド オブジェクトまたはアンマネージド オブジェクトへの永続的な関連付けを持つグラフをフラッシュすることはできません。推奨されるアクション: a) このフィールドの cascade 属性を CascadeType.PERSIST または CascadeType.ALL (JPA アノテーション) または「persist」または「all」 (JPA orm.xml) に設定する、b) cascade-persist をグローバルに有効にする、c) 手動でフラッシュする前に関連するフィールド値を保持します。d) 参照が別のコンテキストに属している場合は、StoreContext.setAllowReferenceToSiblingContext() を設定して参照を許可します。失敗したオブジェクト: com.xxx.yyy.data.entity。


4

2 に答える 2

0

仕様を深く掘り下げない限り、これについてはよくわかりませんが、次のことが起こると思います。

次のように仮定します: F が永続化されている場合、永続化は C および D を介して E にカスケードされます。

ただし、OpenJPA は F をスキャンして、 と の 2 つの関係F.cを確認しF.eます。永続化を C にカスケードしますが、F.eカスケード用にマークされていないため、OpenJPA は E も永続化されることを (まだ) 知りません (F の処理が完了していないため)。したがって、エラーが発生します。

にカスケードを追加するF.eE.d、問題が解決するはずです。

編集:最初に C を (直接またはカスケード経由で) 永続化したとしても、OpenJPA は D の前に F を処理しようとする可能性があります。したがって、F.eが処理されるときに、OpenJPA は E も永続化されることを知りません (カスケードD.eはまだ処理されていません)。 .

これに対するもう 1 つの解決策は、C 内で関連付けの順序を再配置することかもしれません。OpenJPA がどの順序で関連付けを処理してカスケードしたかがわからないので、可能だと言います、正直なところ、どの順序にも依存しませんしたがって、カスケードをF.eetc. に追加することは、より堅牢なオプションのようです。

編集2:

重複持続の問題については、グラフを少し壊してみてください。所有側を考えてみましょう。F は C および E との関係を所有し、E は D との関係を所有し、D は C との関係を所有します。

したがって、C を永続化すると、カスケードには F が含まれ、これに E と D が含まれます。D はとにかく永続化されるため、カスケード on は必要ありC.dません。これにより、重複が発生する可能性があります。C.dとのカスケードを削除してみD.eます。

于 2013-07-23T10:06:50.163 に答える
0

その問題は次のとおりであると仮定します。エンティティ E は 2 回永続化されます。

エンティティ F を永続化する前に、エンティティ F のセッターで setE() と setC() を実行する必要があります。

于 2013-07-23T10:22:11.823 に答える