[Seasar-user:11408] Re: [Kuina-Dao] dao.persist(entity) で,主キー重複エラーを回避するには?

Applied_MATSUDA Masaaki [E-MAIL ADDRESS DELETED]
2007年 11月 2日 (金) 11:52:31 JST


TigerCatです.


小林さま,いつもご返答いただきありがとうございます.m(_ _)m


なるほど,persist()でupdateはできない・・・と.
教示していただいたelse以下がupdateの場合の対応となると思う
のですが,

>  } else {
>    fuga.setXXX(Boolean.TRUE);
>    fuga.setYYY(yyy);
>  }

セットするだけで,あとは何もしなくて良いということです
よね?!
なーんと.

ということは・・・
こちらももっと真面目なサンプルを提示しなければならなかった
かもしれません・・・


実は,実際に作っているものは,2つのテーブルで,ヘッダ情報
とディテール情報を分けて持っており,外部キーの関係を持って
います.
ヘッダとディテールですので,OneToOneかといいますと,ちがい
まして,ディテールの方は修正履歴を保持することにしています
ので,1つのヘッダ上のcodeに対して,複数のversionを持つこと
になり,ManyToOneの関係になっております.

で,もういちど,質問の本当本意をお伝えしますと,
[ヘッダテーブル]
  code = 1
[ディテールテーブル]
  code = 1 | version = 1
と,このように既に1件のデータが入っているとき,このディテ
ールを修正しようとしたとき,要件からすると修正というよりは
code = 1 | version = 2 の新規レコードを作るわけです.

んで,DetailのEntityをnewして,HeaderのEntityもnewして,
値を詰め込んで,detail.setHeader(header)でDetailにHeader
を放り込んだうえで,persisit(detail) したところ,
「先にheaderを保存せい」みたいな例外が出てしまい・・・
なので,persist(header)してからpersist(detail)したところ
「ヘッダのキーが重複するだろがあ」という例外に変わった.
というところが,前回の質問だったのです.
要は,前回のFugaとか書いてるエンティティは,今いうところ
のHeaderなのです.

updateの際はpersisitしない,となると,「先にheaderを保存
せい」の例外に逆戻りしないかなー,と,ちょっと心配です.


>どう対処するかは要件およびトランザクション境界を
>どう設定するかにもよるので一概には言えません.

はい.
いまんところはまずデータが正しくつっこまれるというとこ
ろを確認しているとろこで,その次はトランザクションを
真面目に考えようとしていました.
ChuraProjectなので,デフォルトのトランザクション境界は
Serviceクラスになっていると思いますが,私的には,
さきほどのinsertOrUpdateメソッドの中でトランザクション
をつかまえて,自分でcommitかけようと思っていました.
システム的にはこれらのテーブルを更新できるのはこの
メソッドのみということにしていますので,synchronized
にしとけばとりあえず・・・と.

本当は,SQLでテーブルロックを書いていたんです.
でも,そうするとDBに対する汎用性が無くなってしまう
んですよね.JPAなりHibernateなりが(あ,Kuina-Daoの
独自の実装でもいいけれど)各種DBのテーブルロック等
の方法を隠蔽する仕組みを搭載してくれるといいのですが.
やっぱり,DB自身がロック状態にならないと,今後別シス
テムが出来上がってDBを横からいぢられるような状況に
なったときに困ったことになっちまうんですよね・・・

そんな具合で,次回の質問があるとすれば,
・DBのネイティブロックをかける汎用的な仕掛は??
・(↑あきらめて)insertOrUpdateでトランザクション
  を自分で制御するには??
・select count(*) や,select max(version) をサックリ
  実現する方法は??

なんてところだと思います.
勢いに便乗して三番目なんか書いてますが(爆汗



ではでは.




Seasar-user メーリングリストの案内