我想从数据库表中增加并返回一个计数器。
java代码如下:
String sqlUpdate = "UPDATE mytable SET col3 = col3 + 1 WHERE colpk1 = ? AND colpk2 = ?";
Query queryUpdate = manager.createNativeQuery(sqlUpdate);
queryUpdate.setParameter(1, ...);
queryUpdate.setParameter(2, ...);
int num = queryUpdate.executeUpdate();
if (num == 0) {
long count = 1;
String sqlInsert = "INSERT INTO mytable (colpk1, colpk2, col3) VALUES (?,?,?)";
Query queryInsert = manager.createNativeQuery(sqlInsert);
queryInsert.setParameter(1, ...);
queryInsert.setParameter(2, ...);
queryInsert.setParameter(3, count);
queryInsert.executeUpdate();
return count;
} else {
String sqlSelect = "SELECT col3 FROM mytable WHERE colpk1 = ? AND colpk2 = ?";
Query querySelect = manager.createNativeQuery(sqlSelect);
querySelect.setParameter(1, ...);
querySelect.setParameter(2, ...);
Object result = querySelect.getSingleResult();
return Long.parseLong(result.toString());
}
如果已经存在具有给定主键的行,这也可以同时使用(创建锁)。但是,如果该行尚不存在(num == 0),则 UPDATE 不会锁定,并且两个查询之间可能会发生并发访问,然后在将 INSERT 作为新行执行时导致唯一约束验证在此期间已经创建。
解决这个问题的最佳方法是什么?SELECT FOR UPDATE
首先使用一个然后根据结果执行更新或插入会更好吗?