JdbcTemplate SELECT ... FOR UPDATE - 没有锁定

时间:2014-08-22 11:07:05

标签: java sql spring oracle jdbctemplate

我正在使用 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 作为方法,尝试使用包含INSERTUPDATE/INSERT的单个事务,但它没有工作。 E.g:

@Transactional(isolation=Isolation.SERIALIZABLE,propagation=Propagation.REQUIRES_NEW)

如何确保SELECTUPDATE/INSERT一起运行? (有/无SELECT ... FOR UPDATE@Transactional等)

3 个答案:

答案 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语句并查看它是否锁定。