- PR -

hibernateでのテーブルロックの方法

1
投稿者投稿内容
ゆう
会議室デビュー日: 2005/10/06
投稿数: 3
投稿日時: 2005-10-06 00:52
再帰的なリレーションがあるテーブルで、
hibernateであるレコードを参照しているデータを違うレコードを参照させるように
変更をしたいのですが、
commit()をする前に他より変更前に参照していたレコードを参照しているデータを追加されてしまうと、ひとつだけ違うデータをレコードを参照しているデータができてしまうと思うので、変更時に、他から追加できないようにテーブルにロックをかけたいのですが、方法がわかりません。どなたかご教授お願いします。
また、テーブルロックをかけずとも、上記の問題を解決できる方法がありましたらお願いします。

A,B、C、D
のデータがあり

A←A,B、C、D(A〜DがAを参照している)

B←A、B、C、D(A〜DがBを参照している)
と変更したい場合にhibernateでA〜Dのエンティティを取得し、
外部キーをAからBに変更し、COMMITする間に
他からEを追加されると、
B←B、C、D、A←E
となってしまうと思われます。
参照しているデータを変更できた後はAを参照させない処理を施すことができるのでそれは良いのですが。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2005-10-06 11:09
引用:
A←A,B、C、D(A〜DがAを参照している)

B←A、B、C、D(A〜DがBを参照している)
と変更したい場合にhibernateでA〜Dのエンティティを取得し、
外部キーをAからBに変更し、COMMITする間に他からEを追加されると、
B←B、C、D、A←E
となってしまうと思われます。



各エンティティはそれぞれ独立しているように見えますが、
Eの追加時にAを参照したままだとまずいのは何故でしょう?
A、B、C、D、Eに関係する親エンティティがいるのでは?

もしそうであれば、更新前に親エンティティをLockMode.UPGRADEで
Session#lock()すればうまく行くのではないでしょうか。
ゆう
会議室デビュー日: 2005/10/06
投稿数: 3
投稿日時: 2005-10-06 13:54
ご返信ありがとうございます。
説明が悪かったようで申し訳ありません。

引用:
各エンティティはそれぞれ独立しているように見えますが、
Eの追加時にAを参照したままだとまずいのは何故でしょう?
A、B、C、D、Eに関係する親エンティティがいるのでは?



A〜Eは同じテーブルのレコードです。

以下のような状態になっています。

-----
(ID,親,値)のカラムを持つテーブルが一つ
現在のテーブルの状態(ア)

ア┃ID│親│値
━╋━┿━┿━━━
A ┃1 │1 │aaaaa
B ┃2 │1 │bbbbb
C ┃3 │1 │ccccc
D ┃4 │1 │ddddd

更新後の状態(イ)

イ┃ID│親│値
━╋━┿━┿━━━
A ┃1 │2 │aaaaa
B ┃2 │2 │bbbbb
C ┃3 │2 │ccccc
D ┃4 │2 │ddddd

状態(イ)になったあとに

E ┃5 │1 │aaaaa

を挿入しようとしたらロジックで防ぐ(ID=親じゃないからだめ等)

しかし、(ア→イ)の処理とEの挿入が同時に発生した場合、
以下のようになりうる

プロセスXでテーブルを読み込む(状態ア)
プロセスXでA〜Dの親をB(ID=2)にUPDATEする
プロセスYでテーブルを読み込む(コミットはまだなので状態ア(oracleの動作))
プロセスYでA(ID=1)を親に持つEを挿入する
プロセスYコミット
プロセスXコミット

このとき、すでに親ではないAを親に持つレコードEができてしまう。
(B←A←Eとなり、ここだけ3階層)
-----

引用:
もしそうであれば、更新前に親エンティティをLockMode.UPGRADEで
Session#lock()すればうまく行くのではないでしょうか。


とのアドバイスをいただきましたが、DBがoracleなので、
古いデータが読み込めてしまいます。

あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2005-10-07 00:57
Aの親をBに変更(そもそもAの親がAというのも変ですが)したからと言って、
Eの親をAにしてはまずい、という仕様って何かおかしくないですか?

Aの親がAってのはNULLの代替表現だと思うのですが、違いますか?
そうでなければ無限再帰な参照になってしまうんじゃないでしょうか。

A┬─B
 ├─C
 └─D
  ↓
B┬─A
 │ └─E
 ├─C
 └─D

自己参照型のテーブルは木構造になるので、親子関係も各エンティティ毎に
独立しているはずではないかと。親子関係のルールを定めた親エンティティが
別にいて、非正規化な意味で各エンティティにも参照を持たせてるのでは?

もしこの意味なら親エンティティを作ってUPGRADEなロックで解決しますよ。

#Hibernate用語でのエンティティって、テーブルではなくレコードで、
#永続化されるクラスのインスタンスの意味に近いと捉えています。
ゆう
会議室デビュー日: 2005/10/06
投稿数: 3
投稿日時: 2005-10-07 13:28
あしゅさん、ありがとうございました。
UPGRADEロックで解決いたしました。

やっぱりテーブルの構造がおかしいですよね。
カラムに親を持たせているのは親子関係がほしいからなのですが、
2階層でなければいけないということなので、
親専用テーブルがあればきれいに解決するとおもいます。

今回はこういうテーブルになってしまっているので、
ご教授いただいたUPGRADEロックを取得してという方法で
解決することになりました。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)