繁体   English   中英

JdbcTemplate SELECT…FOR UPDATE-无锁

[英]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用作该方法,以尝试使单个事务同时包含INSERTUPDATE/INSERT ,但这没有用。 例如:

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

如何确定SELECTUPDATE/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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM