Hibernate/楽観的ロックを実装する
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents
Hibernateは業務用アプリとかで出てくる、楽観的ロック機構を...
実装方法は対象のテーブルにバージョンカラムを設けて、更新...
**対象テーブルの情報 [#g644d7c9]
さて実験ですが、複数のトランザクションである同じrowを検索...
#ref(MESSAGES.png)
対象のテーブルMESSAGESは以下の通り:
mysql> describe test.MESSAGES;
+-----------------+------------------+------+-----+-----...
| Field | Type | Null | Key | Defa...
+-----------------+------------------+------+-----+-----...
| MESSAGE_ID | int(10) unsigned | NO | PRI | NULL...
| NEXT_MESSAGE_ID | int(10) unsigned | YES | MUL | NULL...
| MESSAGE_TEXT | varchar(255) | NO | | NULL...
| VERSION | int(10) unsigned | NO | | 0 ...
+-----------------+------------------+------+-----+-----...
このテーブルを作成するために実行するDDLは以下の通り:
CREATE TABLE `MESSAGES` (
`MESSAGE_ID` int(10) unsigned NOT NULL auto_increment,
`NEXT_MESSAGE_ID` int(10) unsigned default NULL,
`MESSAGE_TEXT` varchar(255) character set ujis NOT NUL...
`VERSION` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`MESSAGE_ID`),
KEY `MESSAGES_FKIndex1` (`NEXT_MESSAGE_ID`),
CONSTRAINT `MESSAGES_ibfk_1` FOREIGN KEY (`NEXT_MESSAG...
REFERENCES `MESSAGES` (`MESSAGE_ID`) ON DELETE NO ACTION
ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
**Messages.hbm.xml [#s1a27407]
Hibernateの設定ファイルは以下の通り。VERSIONのカラムの指...
<version name="version" type="int">
<column name="VERSION" not-null="true">
</column>
</version>
となっています。
ちなみにこのファイルは[[Hibernate Tools>Hibernate/Hiberna...
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hiberna...
"http://hibernate.sourceforge.net/hibernate-mapping-3.0....
<!-- Generated 2006/06/19 0:06:47 by Hibernate Tools 3.1...
<hibernate-mapping>
<class name="nu.mine.kino.models.Messages" table="MESS...
<comment></comment>
<id name="messageId" type="int">
<column name="MESSAGE_ID" />
<generator class="increment" />
</id>
<version name="version" type="int">
<column name="VERSION" not-null="true">
<comment></comment>
</column>
</version>
<many-to-one name="messages" class="nu.mine.kino.mod...
<column name="NEXT_MESSAGE_ID">
<comment></comment>
</column>
</many-to-one>
<property name="messageText" type="string">
<column name="MESSAGE_TEXT" not-null="true">
<comment></comment>
</column>
</property>
<set name="messageses" inverse="true">
<key>
<column name="NEXT_MESSAGE_ID">
<comment></comment>
</column>
</key>
<one-to-many class="nu.mine.kino.models.Messages" />
</set>
</class>
</hibernate-mapping>
**やってみる [#l26fc5b6]
以下のように、複数のトランザクションを別スレッドで稼働さ...
new Thread(new Runnable() {
public void run() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
System.out.println("トラ1開始");
Messages message = (Messages) session.load(Messa...
System.out.println(message.getMessageText());
message.setMessageText("Thread1:" + System.curre...
waitt(3000);
tx.commit();
session.close();
System.out.println("トラ1終了");
}
}).start();
new Thread(new Runnable() {
public void run() {
waitt(500);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
System.out.println("トラ2開始");
Messages message = (Messages) session.load(Messa...
System.out.println(message.getMessageText());
waitt(1000);
message.setMessageText("Thread2:" + System.curre...
tx.commit();
session.close();
System.out.println("トラ2終了");
}
}).start();
このように
トラ1開始 select -> トラ2開始 select ->
トラ2update & commit -> トラ1update & commit
としたときに、トラ1のコミットがどうなるかを見てみました...
Start.
[main] INFO org.hibernate.cfg.Environment - Hibernate 3.1
[main] INFO org.hibernate.cfg.Configuration - Reading m...
[main] INFO org.hibernate.cfg.HbmBinder - Mapping class...
[main] INFO org.hibernate.cfg.HbmBinder - Mapping colle...
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: ...
[main] INFO org.hibernate.dialect.Dialect - Using diale...
End.
トラ1開始
[Thread-0] DEBUG org.hibernate.SQL - select messages0_.M...
messages0_.NEXT_MESSAGE_ID as NEXT3_0_0_, messages0_.MES...
where messages0_.MESSAGE_ID=?
Thread2:1151250136968
トラ2開始
[Thread-1] DEBUG org.hibernate.SQL - select messages0_.M...
messages0_.NEXT_MESSAGE_ID as NEXT3_0_0_, messages0_.MES...
where messages0_.MESSAGE_ID=?
Thread2:1151250136968
[Thread-1] DEBUG org.hibernate.SQL - update test.MESSAGE...
where MESSAGE_ID=? and VERSION=?
トラ2終了
[Thread-0] DEBUG org.hibernate.SQL - update test.MESSAGE...
where MESSAGE_ID=? and VERSION=?
Exception in thread "Thread-0" org.hibernate.StaleObject...
transaction (or unsaved-value mapping was incorrect): [n...
at LockSample$1.run(LockSample.java:38)
at java.lang.Thread.run(Unknown Source)
トラ1のスレッドが更新かけてcommitしようとしたときに
Exception in thread "Thread-0" org.hibernate.StaleObject...
Row was updated or deleted by another transaction
という例外が発生しました。トラ2の処理で自動的にVERSIONカ...
----
この記事は
#vote(おもしろかった[57],そうでもない[9])
#comment
#topicpath
SIZE(10){現在のアクセス:&counter;}
終了行:
// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents
Hibernateは業務用アプリとかで出てくる、楽観的ロック機構を...
実装方法は対象のテーブルにバージョンカラムを設けて、更新...
**対象テーブルの情報 [#g644d7c9]
さて実験ですが、複数のトランザクションである同じrowを検索...
#ref(MESSAGES.png)
対象のテーブルMESSAGESは以下の通り:
mysql> describe test.MESSAGES;
+-----------------+------------------+------+-----+-----...
| Field | Type | Null | Key | Defa...
+-----------------+------------------+------+-----+-----...
| MESSAGE_ID | int(10) unsigned | NO | PRI | NULL...
| NEXT_MESSAGE_ID | int(10) unsigned | YES | MUL | NULL...
| MESSAGE_TEXT | varchar(255) | NO | | NULL...
| VERSION | int(10) unsigned | NO | | 0 ...
+-----------------+------------------+------+-----+-----...
このテーブルを作成するために実行するDDLは以下の通り:
CREATE TABLE `MESSAGES` (
`MESSAGE_ID` int(10) unsigned NOT NULL auto_increment,
`NEXT_MESSAGE_ID` int(10) unsigned default NULL,
`MESSAGE_TEXT` varchar(255) character set ujis NOT NUL...
`VERSION` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`MESSAGE_ID`),
KEY `MESSAGES_FKIndex1` (`NEXT_MESSAGE_ID`),
CONSTRAINT `MESSAGES_ibfk_1` FOREIGN KEY (`NEXT_MESSAG...
REFERENCES `MESSAGES` (`MESSAGE_ID`) ON DELETE NO ACTION
ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
**Messages.hbm.xml [#s1a27407]
Hibernateの設定ファイルは以下の通り。VERSIONのカラムの指...
<version name="version" type="int">
<column name="VERSION" not-null="true">
</column>
</version>
となっています。
ちなみにこのファイルは[[Hibernate Tools>Hibernate/Hiberna...
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hiberna...
"http://hibernate.sourceforge.net/hibernate-mapping-3.0....
<!-- Generated 2006/06/19 0:06:47 by Hibernate Tools 3.1...
<hibernate-mapping>
<class name="nu.mine.kino.models.Messages" table="MESS...
<comment></comment>
<id name="messageId" type="int">
<column name="MESSAGE_ID" />
<generator class="increment" />
</id>
<version name="version" type="int">
<column name="VERSION" not-null="true">
<comment></comment>
</column>
</version>
<many-to-one name="messages" class="nu.mine.kino.mod...
<column name="NEXT_MESSAGE_ID">
<comment></comment>
</column>
</many-to-one>
<property name="messageText" type="string">
<column name="MESSAGE_TEXT" not-null="true">
<comment></comment>
</column>
</property>
<set name="messageses" inverse="true">
<key>
<column name="NEXT_MESSAGE_ID">
<comment></comment>
</column>
</key>
<one-to-many class="nu.mine.kino.models.Messages" />
</set>
</class>
</hibernate-mapping>
**やってみる [#l26fc5b6]
以下のように、複数のトランザクションを別スレッドで稼働さ...
new Thread(new Runnable() {
public void run() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
System.out.println("トラ1開始");
Messages message = (Messages) session.load(Messa...
System.out.println(message.getMessageText());
message.setMessageText("Thread1:" + System.curre...
waitt(3000);
tx.commit();
session.close();
System.out.println("トラ1終了");
}
}).start();
new Thread(new Runnable() {
public void run() {
waitt(500);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
System.out.println("トラ2開始");
Messages message = (Messages) session.load(Messa...
System.out.println(message.getMessageText());
waitt(1000);
message.setMessageText("Thread2:" + System.curre...
tx.commit();
session.close();
System.out.println("トラ2終了");
}
}).start();
このように
トラ1開始 select -> トラ2開始 select ->
トラ2update & commit -> トラ1update & commit
としたときに、トラ1のコミットがどうなるかを見てみました...
Start.
[main] INFO org.hibernate.cfg.Environment - Hibernate 3.1
[main] INFO org.hibernate.cfg.Configuration - Reading m...
[main] INFO org.hibernate.cfg.HbmBinder - Mapping class...
[main] INFO org.hibernate.cfg.HbmBinder - Mapping colle...
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: ...
[main] INFO org.hibernate.dialect.Dialect - Using diale...
End.
トラ1開始
[Thread-0] DEBUG org.hibernate.SQL - select messages0_.M...
messages0_.NEXT_MESSAGE_ID as NEXT3_0_0_, messages0_.MES...
where messages0_.MESSAGE_ID=?
Thread2:1151250136968
トラ2開始
[Thread-1] DEBUG org.hibernate.SQL - select messages0_.M...
messages0_.NEXT_MESSAGE_ID as NEXT3_0_0_, messages0_.MES...
where messages0_.MESSAGE_ID=?
Thread2:1151250136968
[Thread-1] DEBUG org.hibernate.SQL - update test.MESSAGE...
where MESSAGE_ID=? and VERSION=?
トラ2終了
[Thread-0] DEBUG org.hibernate.SQL - update test.MESSAGE...
where MESSAGE_ID=? and VERSION=?
Exception in thread "Thread-0" org.hibernate.StaleObject...
transaction (or unsaved-value mapping was incorrect): [n...
at LockSample$1.run(LockSample.java:38)
at java.lang.Thread.run(Unknown Source)
トラ1のスレッドが更新かけてcommitしようとしたときに
Exception in thread "Thread-0" org.hibernate.StaleObject...
Row was updated or deleted by another transaction
という例外が発生しました。トラ2の処理で自動的にVERSIONカ...
----
この記事は
#vote(おもしろかった[57],そうでもない[9])
#comment
#topicpath
SIZE(10){現在のアクセス:&counter;}
ページ名: