2017-06-01 4 views
1

私はsimilarquestionsを知っていますが、Hibernateの範囲で質問され回答されました。私は同じ問題を抱えていますが、私はEclipselinkを使用していて、Hibernateに提案されているものに対してより優れた代替ソリューションがあるかどうか疑問に思っています。Eclipselink/JPAでエンティティタイプを変更しますか?

を私は互いから継承するクラスを持っている::まもなく質問をおさらいする

@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="dtype") 
@DiscriminatorValue(value="parent") 
public class Parent { 
    @Id 
    private long id; 
} 


@Entity 
@DiscriminatorValue(value="child") 
public class Child extends Parent{ 
    private String childProperty; 
} 

今、私は、例えば、親またはその逆に子供を変更したいです

Parent p = new Parent(); 
em.persist(p); 

Child c = (Child) p; 
em.merge(c); 

私は、pのためのデータベースの行が現在dtype = childであることを期待します。

他の方法は次のように次のようになります。この場合

Child c = new Child(); 
em.persist(c); 

Parent c = (Parent) c; 
em.merge(c); 

、私はcdtype = parentchildPropertyの価値を失うと一緒に保存することが期待されます。

ただし、上記の内容は機能しませんが、私が意味することを示すために書きました。

Eclipselinkでこれを行う方法はありますか?

+0

OOPに関して記述したり、サンプルコードを与えて、「変更タイプ」を理解する方法を教えてください。 –

+0

私は説明を延長しました – Bob

+0

最初のウォンステップの後、次は間違っていると思われます。私は(私の理解で)問題 –

答えて

2

オブジェクトをあるタイプから別のタイプに「変更」したい場合は、javaまたはJPA継承の単純な解決策はありません。あなたは、あなたのインスタンスのクローンを作成し、古いものを削除し、その後、JPA /のJava準拠するように新しいものを保持する必要があります。

Child c = em.find(pk, Child.class); 
Parent p = new Parent(); 
p.setId(c.getId()); 
p.setOtherFields(c.getOtherFields()); 

em.getTransaction().begin(); 
em.remove(c); 
em.getTransaction().commit(); 
em.clear(); 
em.getTransaction().begin(); 
em.persist(p); 
em.getTransaction().commit(); 

それはすべてのために同じトランザクションを使用した作業は、フラッシュ使用して代わりの開始/コミット「かもしれません」、二次キャッシュの管理が難しくなるため、保証されません。また、子へのすべての関係を '新しい'親インスタンスまたはキャッシュを指すように更新する必要があることにも注意してください。

この場合、子が親インスタンスであるため、私は実際にはっきりとは分かりません。このアプローチでは、データベース内の任意のフラグ以外の何も得られません。実行中に変更可能にしたい場合は、Javaサブクラスを使用する方がアプリケーションに適したアプローチではない可能性があります。

代わりに、子/親ステータスを保持するために設定できるフィールドを持つ一般的なPersonを使用することをお勧めします。しかし、子供は同時に親になることができます。

+0

ありがとうございました。私がこの解決策に直面している1つの問題は、 'em.remove(c);'もcascade-persistを通じてOneToMany関連オブジェクトを削除するということです。新しい親オブジェクトにOneToMany-Objectsが必要なので、これを回避する方法(カスケード・サスペンドを削除する以外に)を知っていますか? – Bob

+0

それらをヌルにします。とにかく削除する前に参照をクリーンアップしてから、同じ参照を新しいインスタンスに追加する必要があります。これには残念なことに双方向参照の修正が含まれており、余分なステートメントが必要なために最も効率的なアプローチではありません。共有キャッシュを使用していない場合は、リモート参照の修正をスキップして新しいインスタンスを指し示すことができますが、将来はそのアプリケーションを制限する可能性があります。 – Chris

関連する問題