seasar2+hibernate+JPA(1.0)環境における悲観的ロック

| | コメント(0) | トラックバック(0)

背景 - ロック手法について

データベース更新時のロックの方法として、次の2種類が存在する。
  • 悲観的ロック (Pessimistic lock)
  • 楽観的ロック (Optimistic lock)
悲観的ロックは、更新対象を更新完了までロックし、他の人が更新を行ったり、場合によっては参照も禁止する方法。
データをより安全に更新・参照できるメリットがあるが、ロック待ちによるアプリケーションの性能低下要因となりやすい。

楽観的ロックは「自分が操作している情報は他人が同時に更新する可能性が低い」更新を行うのに向いたロック方法。
更新対象を本当に更新する段階までぎりぎりまでロックしない。

例えば、「一旦データを取得したあと、内容を変更して実際に変更しようとしたら、データ取得後に誰かが同じレコードを更新していた」というケースの場合、悲観的ロックであれば「データ取得時に行ロックを行い、誰も更新できない状況」を作ってから更新を行う。その間、他の更新処理は自分の処理が完了するまで待ち状態となる。
一方、楽観的ロックであれば、自分がデータ取得後に他人がデータを更新できてしまう。自分がその後に更新しようとすると JPA 利用時、 OptimisticLockException が発生する。

概要

JPA(Java Persistence API) 1.0では楽観的ロックのみサポートしている。2.0 からは悲観的ロックもサポートするらしい。

Seasar2 + Hibernate + JPA 1.0 の構成において悲観的ロックでデータを更新したいと思い試行錯誤したが、意外とつまづいた。
EntityManager に lock() というメソッドがあって、write lock もできそうだが、うまくいかない。seasar がサポートしていないのか、設定がうまくいっていないのか...

結局、以下の方法で実現できた。

悲観的ロックによる更新方法

次のようなコードになる。
package jp.trasis.sample.service;

import javax.persistence.EntityManager;

import jp.trasis.sample.entity.User;

import org.seasar.extension.tx.annotation.RequiresNewTx;
import org.seasar.framework.container.annotation.tiger.Binding;

public class TestService {
	@Binding
	private EntityManager entityManager;
	
	@RequiresNewTx
	public void test(Long userId, String name) {
		User user = (User) entityManager.createNativeQuery(
				"select * from User_ where id=:userId for update", User.class)
			.setParameter("userId", userId)
			.getSingleResult();
		
		user.setName(name);

		entityManager.persist(user);
	}
}

解説

@RequiresNewTx アノテーションにより、新たなトランザクションの中で更新処理を行う。

まず、更新対象のエンティティを select ... for update により、行ロックを行いながら取得する。
この SQL は createNativeQuery() メソッドで実行する必要がある。crateQuery() で使用する HQL では、 for update 文は利用できない。

そしてエンティティに対して修正を行い、 persist() でコミットを行う。メソッドを抜けるときに実際に DB へのコミット処理が行われ、トランザクションが終了し、ロックも開放される。

トラックバック(0)

このブログ記事を参照しているブログ一覧: seasar2+hibernate+JPA(1.0)環境における悲観的ロック

このブログ記事に対するトラックバックURL: http://trasis.jp/cgi-bin/mt/mt-tb.cgi/84

コメントする

2009年6月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30