Java アプリケーションで、一連の DB ステートメントをアトミックかつ分離された方法で実行する必要があります。たとえば、アプリケーションは、あるテーブルからデータ行を読み取り、別のテーブルのデータ行を更新する必要があります。
QueryRunner queryRunner = new QueryRunner(); // DBUtils query runner
Object[] params = new Object[] { param };
Connection conn = null;
try {
conn = ...; // get connection
conn.setAutoCommit(false);
result = queryRunner.query(conn, "select x, y, z from table1 where column1 = ?", new BeanHandler<SomeBean>(SomeBean.class), params);
// logic to get value for update
queryRunner.update(conn, "update table2 set p = ? where q = ?", some_value, some_id);
conn.commit();
} catch (SQLException e) {
//
} finally {
DBUtils.closeQuietly(conn);
}
トランザクション管理は、上記のように、接続に対して自動コミットを false に設定し、後で明示的にコミットすることによって実現されます。しかし、上記のコードはマルチスレッド環境でも実行できます。また、2 つの DB ステートメント (選択と更新) を相互排他的に全体として実行することも必要です。
以下に示すように、そのメソッドで共有 Java Lock オブジェクトを使用する考えがあります。
クラスでは、
private Lock lock = new ReentrantLock(); // member variable
メソッドでは、
lock.lock();
try {
conn = ...; // get connection
conn.setAutoCommit(false);
result = queryRunner.query(conn, "select x, y, z from table1 where column1 = ?", new BeanHandler<SomeBean>(SomeBean.class), params);
// logic to get value for update
queryRunner.update(conn, "update table2 set p = ? where q = ?", some_value, some_id);
conn.commit();
} finally {
DBUtils.closeQuietly(conn);
lock.unlock();
}
問題を解決する能力があるようです。ただし、これがベストプラクティスであるかどうか疑問に思っており、これに対するより良い代替手段 (フレームワークなど) はありますか?