我正在使用 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>选择> INSERT / UPDATE>插入/更新
但我想要
SELECT> INSERT / UPDATE>选择>插入/更新
我希望在第一个SELECT
之后锁定(SELECT ... FOR UPDATE
的强项),但两个选择都被调用,因此UPDATE/INSERT
不能正常工作。
我还尝试使用 @Transactional
作为方法,尝试使用包含INSERT
和UPDATE/INSERT
的单个事务,但它没有工作。
E.g:
@Transactional(isolation=Isolation.SERIALIZABLE,propagation=Propagation.REQUIRES_NEW)
如何确保SELECT
和UPDATE/INSERT
一起运行? (有/无SELECT ... FOR UPDATE
,@Transactional
等)
答案 0 :(得分:1)
为什么关闭自动提交?
setAutocommit(false);
由于您禁用了自动提交,因此不会立即执行INSERT/UPDATE
。因此,如果您拨打m()
两次,因为它以SELECT
开头,将在执行上一次运行的INSERT/UPDATE
之前再次执行,因此您将看到执行顺序:
SELECT>选择> INSERT / UPDATE>插入/更新强>
您应该在从m()
返回之前提交,或者您应该使用@Transactional
,但不要禁用自动提交。
答案 1 :(得分:1)
而不是SELECT FOR UPDATE然后INSERT或UPDATE你不能发出一个MERGE语句,让数据库为你做艰苦的工作。您可能需要检查您正在合并的表上是否有适当的唯一约束。
void m() {
JdbcTemplate jt;
...
jt.update(mergeLine, objs2, types2); // merge
}
答案 2 :(得分:0)
尝试删除JDBCTemplate并使用简单的jdbc语句并查看它是否锁定。