我的Java應用程序需要以獨立方式執行一組原始數據庫語句。例如,應用程序需要從一個表中讀取數據行並更新另一個表中的數據行。以Java鎖定一組數據庫操作
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並稍後顯式提交來實現,如上所示。但上面的代碼也可以在多線程環境中執行,我也希望兩個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();
}
看來排序解決問題的能力。但是,我想知道這是否是最佳做法,並且有沒有更好的選擇(如框架)?
謝謝,Hiro2k。我相信,我們的應用程序運行在一個servlet容器中,並將在單個JVM中運行。 「SELECT ... FOR UPDATE」可能不適用於我的情況,因爲我正在更新select語句操作的表以外的表中的一行。 – Chen 2012-04-04 17:36:40
沒錯,但是如果你決定添加服務器的另一個實例來進行負載平衡或縮放,那麼你會遇到這個問題。您可以在方法一開始的第二個表格的行中添加「SELECT ... FOR UPDATE」,以便其他人不得不等待它完成。 – Hiro2k 2012-04-04 18:05:05
好點,@ Hiro2k。我會評估我們的使用案例,看看是否可以涵蓋所有這些案例。 – Chen 2012-04-04 18:09:58