Ich habe eine Anforderung in meiner Java-Anwendung, eine Reihe von DB-Anweisungen in einer atomaren & isoliert auszuführen. Beispielsweise muss die Anwendung Datenzeilen aus einer Tabelle lesen und eine Datenzeile in einer anderen Tabelle aktualisieren.Eine Reihe von DB-Operationen in Java sperren
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);
}
Das Transaktionsmanagement durch automatische Einstellung erreicht wird verpflichten für die Verbindung zu falschen und ausdrücklich später begehen, wie oben gezeigt. Aber der obige Code kann auch in einer Multithread-Umgebung ausgeführt werden, und ich möchte auch, dass die beiden DB-Anweisungen (Select & update) ausschließlich als Ganzes ausgeführt werden.
Ich habe eine Idee, ein gemeinsam genutztes Java Lock-Objekt in dieser Methode zu verwenden, unten abgebildet.
in der Klasse
private Lock lock = new ReentrantLock(); // member variable
Bei dem Verfahren
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();
}
Es scheint eine Art fähig, das Problem zu lösen. Ich frage mich jedoch, ob dies die beste Vorgehensweise ist und gibt es dafür eine bessere Alternative (z. B. Rahmen)?
Danke, Hiro2k. Unsere Anwendung läuft in einem Servlet-Container und wird in einer einzigen JVM sein, glaube ich. Das "SELECT ... FOR UPDATE" funktioniert möglicherweise nicht, wenn ich eine Zeile in einer anderen Tabelle als der Tabelle aktualisiere, in der die SELECT-Anweisung ausgeführt wird. – Chen
Richtig, aber wenn Sie sich jemals entscheiden, eine weitere Instanz des Servers zum Lastenausgleich oder zur Skalierung hinzuzufügen, stoßen Sie auf dieses Problem. Sie können die SELECT-Anweisung für UPDATE in der Zeile in der zweiten Tabelle ganz zu Beginn Ihrer Methode hinzufügen, damit andere warten müssen, bis sie beendet ist. – Hiro2k
Guter Punkt, @ Hiro2k. Ich werde unsere Anwendungsfälle an meinem Ende bewerten, um zu sehen, ob alle von ihnen abgedeckt werden können. – Chen