[Seasar-user:11413] Re: [Kuina-Dao] dao.persist(entity) で,主キー重複エラーを回避するには?
Koichi Kobayashi
[E-MAIL ADDRESS DELETED]
2007年 11月 2日 (金) 17:00:44 JST
小林 (koichik) です.
Date: Fri, 02 Nov 2007 11:52:31 +0900
From: "Applied_MATSUDA Masaaki" <[E-MAIL ADDRESS DELETED]>
To: <[E-MAIL ADDRESS DELETED]>
Subject: [Seasar-user:11408] Re: [Kuina-Dao] dao.persist(entity) で,主キー重複エラーを回避するには?
> なるほど,persist()でupdateはできない・・・と.
> 教示していただいたelse以下がupdateの場合の対応となると思う
> のですが,
>
> > } else {
> > fuga.setXXX(Boolean.TRUE);
> > fuga.setYYY(yyy);
> > }
>
> セットするだけで,あとは何もしなくて良いということです
> よね?!
はい.
> ということは・・・
> こちらももっと真面目なサンプルを提示しなければならなかった
> かもしれません・・・
その前に JPA についてきちんと学習した方がよいかと.
Kuina-Dao は EntityManager に対する操作を簡素化しますが,
JPA を隠蔽するものではありません.
> ・DBのネイティブロックをかける汎用的な仕掛は??
JPA の標準的なやり方は EntityManager#lock() を
使うことです.
Kuina-Dao でも Dao に readLock()/writeLock() を
持たせることができます.
# GenericDao を拡張していればデフォルトで使えます.
public void insertOrUpdate(String code) {
Header header = headerDao.find(code);
if (header == null) {
header = new Header();
header.setCode(code);
dao.persist(header);
Detail detail = new Detail(code, 1);
detail.setHeader(header);
header.addDetail(detail);
detailDao.persist(detail);
} else {
headerDao.readLock(header); // ★
int version = detailDao.getMaxVersion(code);
Detail detail = new Detail(code, version + 1);
detail.setHeader(header);
header.addDetail(detail);
detailDao.persist(detail);
}
}
関連にカスケードの設定をしていればもう少し
スッキリとしますが,概ねこんな感じではないかと.
ただし,上記の方法では同じ Header に対する更新を
排他的に行えるだけで,同じ code を持つ新規の
Heder の追加は排他的になりません.
テーブルをロックする方法は JPA にはないので,
別のエンティティを使って同じように排他制御する,
ネイティブ SQL でテーブルロックする,
前回書いたように requiresNew なトランザクションで
例外を拾ってリトライする等々,適切な方法を検討
してください.
> ・(↑あきらめて)insertOrUpdateでトランザクション
> を自分で制御するには??
http://s2container.seasar.org/2.4/ja/tx.html
> ・select count(*) や,select max(version) をサックリ
> 実現する方法は??
http://kuina.seasar.org/ja/user_guide/query.html#SQLによる検索
--
<signature>
<name>Koichi Kobayashi</name>
<e-mail>[E-MAIL ADDRESS DELETED]</e-mail>
</signature>
Seasar-user メーリングリストの案内