我有一个像下面这样的界面
public interface FooDAO {
public void callA(String x);
}
和下面的实现故意使 readonly 为真且不受支持
public class FooDAOImpl implements FooDAO {
//for testing
@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
public void callA(String x) {
//sql update method
}
}
在我的 spring 上下文中,我声明了数据源事务管理器和 tx:annotation-driven。我写了一个 Junit4 测试,看起来像
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(...)
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
public class MyTest {
@Resource
FooDAO fooDAO;
@Test
public void testRegisterWorker() {
fooDAO.callA("")
}
}
我本以为记录根本不会被插入到数据库中。但是我看到该行实际上已插入到数据库中。我确实使用 Oracle 数据库,所以我认为自动提交默认设置为 true(我认为)。但是 spring 交易标签不应该覆盖它们吗?
谁能告诉我这里出了什么问题?
最佳答案
自动提交可能是默认开启的。使用 DataSourceTransactionManager,只有 事务实际启动时才会更改自动提交。 NOT_SUPPORTED 或 SUPPORTS 都不会启动事务,因此连接处于的任何默认状态都将保持不变。
考虑在 Spring xml 文件中默认关闭自动提交。如果启用,Spring 将不得不在每次 tx 之前更改它并在之后恢复它,这在 Oracle 中可能是昂贵的(不确定)。这也可以防止您意外地在事务之外提交。
有关详细信息,请参阅 org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin()
,它管理连接的自动提交和隔离级别。如果传播是 REQUIRED、REQUIRES_NEW 或 PROPAGATION_NESTED,doBegin() 仅由 AbstractPlatformTransactionManager.getTransaction()
和 handleExistingTransaction()
调用。
您可能想看看 org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests
。这是一个可用于测试类的 Spring 感知基类。它将在每个测试用例结束时回滚任何事务。这样就不需要为了测试而更改注释。您可以将 @Transactional 设置为它们应该在产品中的方式,并依靠回滚来确保在测试期间数据库中没有任何实际更改。
关于java - Spring 什么时候不应该提交? (与 Oracle 自动提交相关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3110750/