如何让 Spring JdbcTemplate 处于 read_uncommissed 状态?

Bre*_*yan 8 java spring jdbc spring-jdbc jdbctemplate

首先,我不能使用声明性@Transactional方法,因为应用程序有多个 JDBC 数据源,我不想厌倦细节,但只要说 DAO 方法传递了正确的数据源来执行逻辑就足够了。所有 JDBC 数据源都具有相同的架构,当我为 ERP 系统公开其余服务时,它们是分开的。

由于这个遗留系统,有很多我无法控制的长期锁定记录,所以我想要脏读。

使用 JDBC 我将执行以下操作:

private Customer getCustomer(DataSource ds, String id) {
    Customer c = null;
    PreparedStatement stmt = null;
    Connection con = null;
    try {
        con = ds.getConnection();
        con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        stmt = con.prepareStatement(SELECT_CUSTOMER);
        stmt.setString(1, id);
        ResultSet res = stmt.executeQuery();
        c = buildCustomer(res);
    } catch (SQLException ex) {
        // log errors
    } finally {
        // Close resources
    }
    return c;
}
Run Code Online (Sandbox Code Playgroud)

好吧,我知道有很多样板。JdbcTemplate所以自从我使用spring以来我就尝试过。

使用Jdbc模板

private Customer getCustomer(JdbcTemplate t, String id) {
    return t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id);
}
Run Code Online (Sandbox Code Playgroud)

好多了,但它仍然使用默认的事务隔离。我需要以某种方式改变这一点。所以我考虑使用TransactionTemplate.

private Customer getCustomer(final TransactionTemplate tt,
                             final JdbcTemplate t,
                             final String id) {
    return tt.execute(new TransactionCallback<Customer>() {
        @Override
        public Customer doInTransaction(TransactionStatus ts) {
            return t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

但是这里如何设置事务隔离呢?我在回调或执行此操作的任何地方都找不到它TransactionTemplate

我正在阅读《Spring in Action,第三版》,其中就我所做的进行了解释,尽管有关事务的章节继续使用带有注释的声明性事务,但正如前面提到的,我不能使用它,因为我的 DAO 需要确定运行时根据提供的参数使用哪个数据源,在我的例子中是国家/地区代码。

任何帮助将不胜感激。

Bre*_*yan 6

我目前已经通过DataSourceTransactionManager直接使用解决了这个问题,尽管看起来我没有像我最初希望的那样节省那么多的样板。不要误会我的意思,它更干净,尽管我仍然忍不住觉得必须有一种更简单的方法。我不需要读取事务,我只想设置隔离。

private Customer getCustomer(final DataSourceTransactionManager txMan,
                             final JdbcTemplate t,
                             final String id) {
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

    TransactionStatus status = txMan.getTransaction(def);
    Customer c = null;
    try {
        c = t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id);
    } catch (Exception ex) {
        txMan.rollback(status);
        throw ex;
    }
    txMan.commit(status);
    return c;
}
Run Code Online (Sandbox Code Playgroud)

我仍然会暂时不回答这个问题,因为我坚信一定有更好的方法。

请参阅Spring 3.1.x 文档 - 第 11 章 - 事务管理