【问题标题】:Database deadlock during Spring JUnit with before-after sqlSpring JUnit期间的数据库死锁与前后sql
【发布时间】:2017-08-29 12:10:09
【问题描述】:

在我的 SpringBoot 应用程序中,我有一个简单的测试用例,我想要这个: 在测试之前将一些数据插入数据库 在测试中做一些验证 测试后从数据库中删除数据 我是这样写的:

存放sql-s的接口。

@Target(METHOD)
@Retention(RUNTIME)
@Sql(scripts = "/insert-data-before.sql", config = @SqlConfig(transactionMode = ISOLATED), executionPhase = BEFORE_TEST_METHOD)
@Sql(scripts = "/delete-data-after.sql", config = @SqlConfig(transactionMode = ISOLATED), executionPhase = AFTER_TEST_METHOD)
public @interface PrepareAndRollbackDataForTesting {
}

测试类:

@RunWith(SpringRunner.class)
@ConfigurationProperties(prefix = "server")
@SpringBootTest(classes = MyTestApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@Transactional
public abstract class MyTestClass {
    @Test
    @PrepareAndRollbackDataForTesting
    public void testTheData() {
        //do something
    }
}

插入数据之前.sql:

BEGIN TRANSACTION;
INSERT INTO mytable(id, name) VALUES (1, 'test');
COMMIT;

delete-data-after.sql:

BEGIN TRANSACTION;
DELETE FROM mytable;
COMMIT;

但如果我这样写,它会以死锁告终。

如果我从界面中删除delete-data-after.sql @Sql,它可以正常工作!

另外,如果我从界面的@Sql-s 中删除配置,它工作正常!

但是我想在单独的事务中运行插入和删除sql,以确保无论方法内部发生什么,它都会删除所有数据,即使出现异常!

【问题讨论】:

  • 您使用什么数据库进行测试?大多数嵌入式数据库不支持多事务。
  • 在这里发布你的表结构+死锁图
  • 谢谢大家,但我终于有答案了!

标签: java sql-server spring junit deadlock


【解决方案1】:

我发现了!

我只需要从界面中删除配置:

@Target(METHOD)
@Retention(RUNTIME)
@Sql(scripts = "/insert-data-before.sql", executionPhase = BEFORE_TEST_METHOD)
@Sql(scripts = "/delete-data-after.sql", executionPhase = AFTER_TEST_METHOD)
public @interface PrepareAndRollbackDataForTesting {
}

因为@Transactional注解会处理事务,之后会回滚。

编辑:

我还从 sqls 中删除了 BEGIN TRANSACTION 和 COMMIT 东西。

【讨论】:

  • 或者不要自己开始交易。您已经为脚本启动了一个新事务的配置,以便之后提交它。当您开始另一笔交易时,您遇到了僵局。
  • 哦,是的,我忘了提到我从 sqls 中删除了 BEGIN TRANSACTION 和 COMMIT 东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 2014-02-28
  • 2012-09-17
  • 1970-01-01
相关资源
最近更新 更多