[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 メーリングリストの案内