public long transactionGetAndIncrement(Connection conn, long id) throws Exception {
// 为了简化,不适用try...finally的方式释放Statement和ResultSet等资源
conn.setAutoCommit(false);
Long expect = null;
// 读取当前值
String sql = "SELECT FValue FROM T_TEST_CAS T WHERE FID = ? FOR UPDATE";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) expect = rs.getLong(1);
rs.close();
stmt.close();
if (expect == null) {
conn.commit();
throw new Exception("id '" + id + "' invalid.");
}
// 更新加1
sql = "UPDATE T_TEST_CAS SET FValue = ? WHERE FID = ?";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, expect.longValue() + 1);
stmt.setLong(2, id);
int updateCount = stmt.executeUpdate();
stmt.close();
if (updateCount == 0) throw new Exception("id '" + id + "' invalid.");
conn.commit();
return expect.longValue();
}
CAS方式的实现
// 为了简化,不适用try...finally的方式释放Statement和ResultSet等资源
public long casGetAndIncrement(Connection conn, long id) throws Exception {
for (;;) { // 外循环
Long expect = null;
String sql = "SELECT FValue FROM T_TEST_CAS T WHERE FID = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
expect = rs.getLong(1);
}
rs.close();
stmt.close();
if (expect == null) throw new Exception("id '" + id + "' invalid.");
// 比较更新
sql = "UPDATE T_TEST_CAS SET FValue = ? WHERE FID = ? AND FValue = ?";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, expect.longValue() + 1);
stmt.setLong(2, id);
stmt.setLong(3, expect.longValue());
int updateCount = stmt.executeUpdate();
stmt.close();
// 如果updateCount > 0,更新成功,返回退出循环,否则回退重来
if (updateCount > 0) return expect.longValue();
}
} |