2

有人可以解释为什么第一个单元测试类有效,而第二个测试类因锁定等待超时错误而失败?

第一个测试班:

public class Test1 extends AbstractTransactionalJUnit4SpringContextTests {

    @Before
    public void setUp() {
       // do stuff through hibernate to populate database with test data
    }

    @Test
    @Transactional(propagation = Propagation.NEVER)
    public void testDeleteObject() {

    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
               // execute sql that deletes data populated in setUp() [i.e. this will require locks on the objects].
            }
        });
    }
}

第二个测试类【获取锁等待超时错误】:

public class Test2 extends AbstractTransactionalJUnit4SpringContextTests {

    @Before
    public void setUp() {
       // do stuff through hibernate to populate database with test data
    }

    @Test
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void testObject() {

    // execute sql that deletes data populated in setUp() [i.e. this will require locks on the objects].

    }
}

我知道第二个测试类失败了,因为这两个事务正在争夺相同的锁,但由于其 in_progress 事务状态,两者都不能放弃锁。我很困惑的是为什么第一个测试类成功执行了 sql。我可能理解错了,但是当 transactionTemplate 执行事务回调时,不会创建新事务吗?在那种情况下,不应该发生同样的事情(锁定等待超时)吗?

4

2 回答 2

2

TransactionTemplate 默认不创建新事务。默认传播行为是 PROPAGATION_REQUIRED。在您的第一种情况下,没有锁定问题,因为设置和删除是在同一个事务中完成的。

您可以通过将 org.springframework.orm.jpa.JpaTransactionManager 类(甚至整个 org.springframework 包)的日志级别设置为 DEBUG 来查看何时创建新事务或重用现有事务。

传播行为的 Javadoc

于 2012-09-24T08:26:28.060 回答
1

只有当有两个或多个连接访问相同的数据时才会发生死锁。如果使用传播注释的测试用例,NEVER您只有一个事务,一个由TransactionTemplate.

第二种情况对我来说有点模糊。异常意味着有两个并发连接/事务 - 一个 forsetUp和一个 for testObjectREQUIRES_NEW即使检测到一个连接,传播确实会强制执行另一个连接,但我也希望setUp在此事务中启动。你可以尝试摆脱@TransactionaltestObject。用我相信的默认传播对其自身进行AbstractTransactionalJUnit4SpringContextTests注释。@TransactionalREQUIRED

于 2012-04-28T10:21:11.467 回答