のでは、通常ではが扱えないようです。ただし、ジャーナル処理を設定すれば扱えるようになるみたいです。*1
で、今回の。
- ジャーナルは作成しない
- IDはテーブルを使って採番
という方針があり、それと関連してFOR UPDATEについてあれこれ調べたりしてました。
さて、には「synchronized」という修飾子があるそうです。これをメソッドの宣言に記述すれば、排他処理が行えるとのこと。
の synchronizedメソッド‐(ββ)
というわけで、のサービスにid採番用のメソッドを書いてみます。
- 採番用テーブルのカラムはとvalueのみ
- エンティティを作成して自動生成で記述
- 各サービスから扱えるようにAbstractServiceに定義
- 最初の採番時、対象キーのが無くても動作可
- valueカラムの現在値=次に採番される値
こんな感じの仕様です。
public abstract class AbstractServiceextends S2AbstractService { public synchronized int generateId(String key) { int id; IdGenerator idGen = jdbcManager .from(IdGenerator.class) .where("key = ?", key) .getSingleResult(); if (idGen == null) { id = 1; idGen = new IdGenerator(); idGen.key = key; idGen.value = 2; jdbcManager.insert(idGen).execute(); } else { id = idGen.value; idGen.value = id + 1; jdbcManager.update(idGen).execute(); } return id; }}
で、synchronizedが実際に効くのかどうか試してみましたが、いまいちわかりませんでした。
- は無しに設定
- メソッドの採番中にユーザーAのみ分岐されるThread#sleep()を仕込む
- ユーザーAにて採番実行
- ユーザーBにて採番実行
こんな手順でやってみたのですが、synchronizedがない状態でも3の時点で止まってくれました。おそらく検証方法がまずいのか、理解が足りないかのどちらかかと思われますが…。考えてもわからないので、ひとまず一区切りとしたいと思います。