読者です 読者をやめる 読者になる 読者になる

No Bugs, No Life

読んだ本や、プログラミング、システム開発等のねたを中心に。文章を書く練習なので少し硬派に書くつもりだけど、どうなることやら。

EclipseLink-JPA 親子エンティティの保管(Cascade.PERSISTの使用)

DEV MW JPA

MementoWeaver開発記
親-子関係のあるエンティティの永続化の時に一寸怒られたのでメモ。

問題の状況

親子関係のあるMaterial, TaggedMaterialエンティティをEclipseLinkを用いて永続化しようとした際に、親エンティティ(Material)の永続化時に怒られた。

例外メッセージ

[EL Warning]: 2013-03-17 20:04:38.005--UnitOfWork(1692946355)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: nobugs.nolife.mw.persistence.TaggedMaterial@7b009a55.
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

ER図

f:id:kazyury:20130309101706p:plain

例外を生じたjava

public void updateTagProcess(Material m){
	EntityManager em = PersistenceUtil.getMWEntityManager();
	em.getTransaction().begin();
	em.merge(m);
	em.getTransaction().commit();
	em.close();
}

対応

例外メッセージによると、同期処理(親子エンティティのpersist)を行う時に、cascade=PERSIST としてマークされていない関連上で新たなオブジェクトが発見されたということなので、メッセージに従ってcascade=PERSISTと指定してみる。

Material->TaggedMaterialのリレーションにcascade=PERSISTを指定

親エンティティであるMaterial.java上で該当するリレーションを選択(@JPAパースペクティブ)し、JPA Detailsビューから画面でポチッとCASCADEオプションを設定する。
f:id:kazyury:20130317204412p:plain

結果

OK*1
TaggedMaterialにもレコードが保管されている*2
f:id:kazyury:20130317205952p:plain

*1:実は、最初のjavaコードではpersist()としていたので、Cascade問題解決後もキー重複で怒られた

*2:年齢計算ロジックはまだ実装していないので0歳でOK