【问题标题】:How do I "obtain transaction-synchronized Session for current thread" in a Micronaut / Kotest / Hibernate test如何在 Micronaut / Kotest / Hibernate 测试中“获取当前线程的事务同步会话”
【发布时间】:2021-03-10 14:39:25
【问题描述】:

我正在尝试在每个组件测试之后清理我的组件测试使用的数据库,以便下一个它是空白的。为此,我有以下内容:

@MicronautTest
class ExampleTest(
    private val entityManager: EntityManager
) : BehaviorSpec() {

    override fun afterEach(testCase: TestCase, result: TestResult) {
        entityManager.transaction.begin()
        entityManager.createQuery("delete from DeviceEntity").executeUpdate()
        ementityManagertransaction.commit()
        entityManager.clear()
    }
    
    /* test code */
}

但是,当我运行它时,我收到以下错误:

Could not obtain transaction-synchronized Session for current thread
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at io.micronaut.transaction.hibernate5.MicronautSessionContext.currentSession(MicronautSessionContext.java:100)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:479)
    at io.micronaut.configuration.hibernate.jpa.TransactionalSessionInterceptor.intercept(TransactionalSessionInterceptor.java:56)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:82)
    at io.micronaut.configuration.hibernate.jpa.TransactionalSession$Intercepted.unwrap(Unknown Source)
    at uk.arqit.cloud.device.core.service.v1.services.component.example.ExampeTest.afterEach(IncrementRatchetSuccessTest.kt:56)
...

我在其他帖子中看到提到使用@Transaction 来装饰方法或从会话工厂获取实体管理器,但使用这些时错误是相同的。

在我的测试的init { ... } 子句(即测试代码所在的位置)中运行此代码没有问题,并且它完全按预期工作。但如果我在afterEach 中运行它,就会出现问题。

谁能提供一些关于如何解决这个问题的建议?

谢谢!

【问题讨论】:

  • 我认为@MicronautTestrollback 的默认值是true。您的测试方法是否插入了未回滚的数据?
  • 他们看起来。我尝试使用 liquibase 发出回滚(我正在使用它进行设置),但这并不影响它 - 显然 INSERT 命令不会生成自己的回滚信息,因此它不起作用。我正在使用实体管理器在需要清除的表上发出“从 x 中删除”命令
  • 由于@MicronautTest 存在而在测试方法中进行的修改是否与正在启动的事务相同?
  • 他们是,但我已经对其进行了修改,使其按照以下解决方案的工作方式工作。即使我开始了一项新事务或尝试同步现有事务,它也会引发错误,因此更简单的选择似乎是创建我自己的事务,而不是要求 Micronaut 为我注入一个事务。值得一提的是,我的实际解决方案是在课程开始时创建它,所以 before/after/init 都共享它(这很好用)。
  • “即使我开始一项新事务或尝试同步现有事务,它也会引发错误......” - 有趣。您应该能够使用现有的交易。这就是我们开始它的原因。从问题中的代码中不清楚为什么会发生这种情况。

标签: java hibernate kotlin micronaut kotest


【解决方案1】:

找到解决办法,先将SessionFactory添加到构造函数中:

@MicronautTest
class ExampleTest(
    private val entityManager: EntityManager,
    private val sessionFactory: SessionFactory
) : BehaviorSpec() {
    
    afterEach(...) {
        ...
    }
}

afterEach方法中有以下内容:

    override fun afterEach(testCase: TestCase, result: TestResult) {
        val sesh = sessionFactory.openSession()
        val em = sesh.entityManagerFactory.createEntityManager()

        /* do whatever you want with 'em' */
    }

值得一提的是,您还可以在类主体中声明seshem,以便所有方法都可以访问它们

【讨论】:

    猜你喜欢
    • 2015-02-04
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2015-04-11
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多