Spring 在不应该提交的时候提交? (与 Oracle 自动提交有关)

Posted

技术标签:

【中文标题】Spring 在不应该提交的时候提交? (与 Oracle 自动提交有关)【英文标题】:Spring commits when it should not ? (related to Oracle autocommit) 【发布时间】:2010-06-24 14:14:01 【问题描述】:

我有一个类似下面的界面

public interface FooDAO 
  public void callA(String x);

下面的实现故意使 readonly 为 true 且不受支持

public class FooDAOImpl implements FooDAO 

  //for testing
  @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) 
  public void callA(String x) 
     //sql update method
  

在我的 spring 上下文中,我声明了 Datasource 事务管理器和 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事务标签不应该覆盖它们吗?

谁能告诉我这里出了什么问题?

【问题讨论】:

【参考方案1】:

自动提交可能默认开启。使用 DataSourceTransactionManager,只有在 事务实际启动时才会更改自动提交。 NOT_SUPPORTED 或 SUPPORTS 都不会启动事务,因此无论连接处于何种默认状态都将保持不变。

考虑在您的 Spring xml 文件中默认设置关闭自动提交。如果启用,Spring 将不得不在每次 tx 之前更改它并在之后恢复它,这在 Oracle 中可能会很昂贵(不确定)。这也可以防止您在事务之外意外提交。

有关详细信息,请参阅org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(),它管理 Connection 的自动提交和隔离级别。 doBegin() 仅在传播为 REQUIRED、REQUIRES_NEW 或 PROPAGATION_NESTED 时由 AbstractPlatformTransactionManager.getTransaction()handleExistingTransaction() 调用。


您可能想看看org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests。这是一个可用于测试类的 Spring 感知基类。它将在每个测试用例结束时回滚所有事务。这样就不需要为了测试而更改注释。您可以将 @Transactional 设置为它们应该在 prod 中的方式,并依靠回滚来确保在测试期间数据库中没有任何实际更改。

【讨论】:

【参考方案2】:

自动提交是 JDBC 的“特性”,而不是 Oracle(在 Oracle 中,所有 DML 语句都是事务的一部分,因此只有在应用程序发出提交时才会提交)。

大多数驱动程序在创建与数据库的连接时将自动提交设为默认值。您可以通过调用setAutoCommit 方法来更改您的连接行为。

【讨论】:

【参考方案3】:

为了使用@TransactionConfiguration,您应该注释您的测试类或测试方法@Transactional。此外,由于propagation = Propagation.NOT_SUPPORTED,您的 DAO 方法可能在没有事务的情况下运行。

【讨论】:

以上是关于Spring 在不应该提交的时候提交? (与 Oracle 自动提交有关)的主要内容,如果未能解决你的问题,请参考以下文章

使用git提交代码--在不切换分支的情况下向不同的分支提交代码

spring与hibernate整合事务管理的理解

如何在不提交表单的情况下使用struts2提交标签作为按钮?

Rails - 如何在不更改页面和更新视图的情况下提交表单?

有没有办法在不提交版本的情况下“修改版本”?

spring ibatis 框架 点击添加按钮 出现了插入两条相同的数据 可能原因 是 ? 求各位大神 指教~