首先,我不能使用声明性的 @Transactional
方法,因为应用程序有多个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;
}
好吧,很多' of boiler-plate, I know. So I'已经尝试了 JdbcTemplate
,因为我正在使用spring .
使用JdbcTemplate
private Customer getCustomer(JdbcTemplate t, String id) {
return t.queryForObject(SELECT_CUSTOMER, new CustomerRowMapper(), id);
}
更好,但它仍然使用默认事务隔离 . 我需要以某种方式改变这一点 . 所以我想到了使用 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);
}
});
}
但是如何在此处设置事务隔离?我无法在回调的任何地方找到它或 TransactionTemplate
来做到这一点 .
我正在阅读Spring in Action,第三版,它解释了我已经完成的事情,尽管关于事务的章节继续使用带注释的声明式事务,但如上所述我不能使用它,因为我的DAO需要确定运行时基于提供的参数使用的数据源,在我的例子中是国家代码 .
任何帮助将不胜感激 .
3 回答
使用
TransactionTemplate
可以帮助您,您需要适当地配置它 . 事务模板还包含事务配置 . 实际上TransactionTemplate
延伸DefaultTransactionDefinition
.所以在你的配置中你应该有这样的东西 .
如果您随后将此bean注入您的类,您应该能够使用之前发布/尝试过的基于
TransactionTemplate
的代码 .但是,可能有一个更好的解决方案可以清理您的代码 . 对于我参与的其中一个项目,我们有与您相似的设置(单个应用程序多个数据库) . 为此我们写了一些spring代码,它基本上在需要时切换数据源 . 更多信息可以在here找到 .
如果你的应用程序是远程提取或过度杀戮,你也可以尝试使用Spring的AbstractRoutingDataSource,它基于查找键(在你的例子中是国家代码)选择要使用的正确数据源 .
通过使用这两种解决方案中的任何一种,您都可以开始使用spring declarative transactionmanagement方法(这应该会大大清理您的代码) .
我目前通过直接使用_1373350解决了这个问题,虽然看起来好像我错了,但是我觉得必须有一个更简单的方法 . 我不需要读取事务,我只想设置隔离 .
我仍然会在一段时间内保持这一点,因为我真的相信必须有更好的方法 .
参考Spring 3.1.x Documentation - Chapter 11 - Transaction Management
定义代理数据源,类为org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy并设置事务隔离级别 . 通过setter或构造函数注入实际数据源 .