[Seasar-user:11393] Re: [Kuina-Dao] dao.persist(entity) で,主キー重複エラーを回避するには?
Koichi Kobayashi
[E-MAIL ADDRESS DELETED]
2007年 11月 1日 (木) 19:00:36 JST
小林 (koichik) です.
Date: Thu, 01 Nov 2007 18:10:12 +0900
From: "Applied_MATSUDA Masaaki" <[E-MAIL ADDRESS DELETED]>
To: <[E-MAIL ADDRESS DELETED]>
Subject: [Seasar-user:11391] [Kuina-Dao] dao.persist(entity) で,主キー重複エラーを回避するには?
> Serviceクラスのコードではこのようなことをやっています.
>
> synchronized public void insertOrUpdate(String code, Integer yyy) {
> Fuga fuga = new Fuga();
> fuga.setCode(code); // 主キーなんですよこれが.
> fuga.setXXX(Boolean.TRUE);
> fuga.setYYY(yyy);
> dao.persist(fuga);
> }
>
> codeが主キーなんですけれど,
> updateしたくて,レコード上に既にある"1"とかを指定して
> 実行すると上記のどっかんです.
JAP の persist() は INSERT 相当なのでそうなります.
INSERT OR UPDATE 相当の機能はありません.
public void insertOrUpdate(String code, Integer yyy) {
Fuga fuga = dao.find(code);
if (fuga == null) {
fuga = new Fuga();
fuga.setCode(code);
fuga.setXXX(Boolean.TRUE);
fuga.setYYY(yyy);
dao.persist(fuga);
} else {
fuga.setXXX(Boolean.TRUE);
fuga.setYYY(yyy);
}
}
のようにしてください.
ただし,同じタイミングで別のトランザクションが
同じ主キーを持つオブジェクトを persist() すると
どちらかが例外になります.
そのタイミングは persist() の時とは限らず,
トランザクションをコミットする時になる場合も
あります.
# このケースではコミット時になるはず.
どう対処するかは要件およびトランザクション境界を
どう設定するかにもよるので一概には言えません.
この insertOrUpdate() メソッドだけ requiresNew で
実行して,その外側で例外をキャッチした場合は
もう一度 insertOrUpdate() を実行する (今度は
find() が null を返さないので成功するはず) などの
方法があります.
その場合は外側のトランザクションをロールバック
しても INSERT/UPDATE が取り消せなくなるので
注意が必要です.
なお,上記のメソッドに synchronized が
付いていますが,DB アクセスに関して
synchronized で排他制御しても,ほとんどの
場合は無力ではないかと思います.
--
<signature>
<name>Koichi Kobayashi</name>
<e-mail>[E-MAIL ADDRESS DELETED]</e-mail>
</signature>
Seasar-user メーリングリストの案内