代码之家  ›  专栏  ›  技术社区  ›  Kannan Ekanath

春天的承诺何时不应该?(与Oracle自动提交相关)

  •  3
  • Kannan Ekanath  · 技术社区  · 14 年前

    我有如下界面

    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驱动的。我写了一个看起来像

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(...)
    @TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
    public class MyTest {
    
        @Resource
        FooDAO fooDAO;
    
        @Test
        public void testRegisterWorker() {
            fooDAO.callA("")
        }
    }
    

    I would have expected the record to not be inserted into the database at all. 然而,我看到行实际上已经插入到数据库中了。我确实使用了Oracle数据库,所以我认为自动提交在默认情况下设置为true(我认为)。但是Spring事务性标签不应该覆盖它们吗?

    有人能告诉我这里出了什么事吗?

    3 回复  |  直到 14 年前
        1
  •  4
  •   AngerClown    14 年前

    默认情况下,“自动提交”可能处于打开状态。对于DataSourceTransactionManager,只更改自动提交 如果 实际启动了一个事务。既不支持也不支持启动事务,因此连接所处的默认状态将保持不变。

    考虑在SpringXML文件中默认设置autocommit关闭。如果启用了它,Spring将在每次发送之前更改它,然后恢复它,这在Oracle中可能很昂贵(不确定)。这还可以防止在事务之外意外提交。

    有关详细信息,请参见 org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin() 它管理连接的自动提交和隔离级别。dobegin()仅由调用 AbstractPlatformTransactionManager.getTransaction() handleExistingTransaction() 如果需要传播,则需要“新建”或“嵌套传播”。


    你可能想看看 org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests . This is a Spring aware base class you can use for your test classes. 它将在每个测试用例结束时回滚任何事务。This way there is no need to change the annotations just for test. 您可以按照prod中的方式设置@transactional,并依靠回滚来确保测试期间数据库中没有任何实际更改。

        2
  •  0
  •   Vincent Malgrat    14 年前

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

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

        3
  •  0
  •   axtavt    14 年前

    为了使用 @TransactionConfiguration 您应该注释您的测试类或测试方法 @Transactional . 另外,由于 propagation = Propagation.NOT_SUPPORTED .