[英]JdbcTemplate SELECT … FOR UPDATE - no lock
我正在使用Spring框架中的JdbcTemplate 。
该数据库是Oracle 。
简化代码:
void m() {
setAutocommit(false); // the same result with/without this line (by default: true )
JdbcTemplate jt;
...
String selectForUpdateLine = "SELECT X FROM T ... FOR UPDATE";
int x = jt.queryForList(selectForUpdateLine, objs, types, Smth.class).size();
...
addDelay(); // to be sure that I can simulate 2 consecutive SELECTs (just for test)
...
if ( x == 0 )
jt.update(insertLine, objs2, types2); // insert
else
jt.update(updateLine, objs2, types2); // update
}
如果我两次调用m()
,它将执行:
选择>选择>插入/更新>插入/更新
但我想要
选择>插入/更新>选择>插入/更新
我期望在第一个SELECT
之后具有锁定(根据SELECT ... FOR UPDATE
),但是两个选择都被调用,因此UPDATE/INSERT
不能很好地工作。
我还尝试将@Transactional
用作该方法,以尝试使单个事务同时包含INSERT
和UPDATE/INSERT
,但这没有用。 例如:
@Transactional(isolation=Isolation.SERIALIZABLE,propagation=Propagation.REQUIRES_NEW)
如何确定SELECT
和UPDATE/INSERT
将一起运行? (使用/不使用SELECT ... FOR UPDATE
,@ @Transactional
等)
为什么关闭自动提交功能?
setAutocommit(false);
由于您禁用了自动提交,因此不会立即执行INSERT/UPDATE
。 因此,如果您两次调用m()
,因为它以SELECT
开头,因此将在执行上一次运行的INSERT/UPDATE
之前再次执行SELECT
,因此您将看到一个执行顺序:
选择>选择>插入/更新>插入/更新
您应该在从m()
返回之前提交,或者应该使用@Transactional
但不要禁用自动提交。
除了执行SELECT FOR UPDATE,然后执行INSERT或UPDATE之外,您不能只发出一个MERGE语句,而是让数据库为您完成艰苦的工作。 您可能需要检查要合并到的表上是否具有适当的唯一约束,例如
void m() {
JdbcTemplate jt;
...
jt.update(mergeLine, objs2, types2); // merge
}
尝试删除JDBCTemplate并使用简单的jdbc语句,看看它是否锁定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.