如何在 Spring 中创建非事务性 JUnit 集成测试?

Ste*_*ers 1 java spring hibernate jpa transactions

集成测试类注释为:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = IntegrationTestConfig.class)
Run Code Online (Sandbox Code Playgroud)

它不应该在事务中运行,所以没有被标记为@Transactional但是当我尝试对 执行持久化、合并等操作时出现错误EntityManager,使用注入@PersistenceContext

没有可用的事务 EntityManager

如何解决这个问题?

编辑: 根据评论中的要求,Spring 版本为 4.1.0.RELEASE,IntegrationTestConfig如下所示:

@EnableAspectJAutoProxy
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@Configuration
public class IntegrationTestConfig {
    /**
     * Override the existing JPA data source bean with a test data source.
     * @return test data source
     */
    @Bean
    public DataSource dataSource() {
        final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(org.h2.Driver.class);
        dataSource.setUrl("jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS mydb");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        return dataSource;
    }
}
Run Code Online (Sandbox Code Playgroud)

man*_*ish 6

如果您确定永远不会调用entityManager.flush(),请PersistenceContext按如下方式获取:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
Run Code Online (Sandbox Code Playgroud)

为什么需要这个?Spring Data JPAEntityManager在使用@PersistenceContext注解(没有任何属性)时分发所谓的共享。在JavaDocs fororg.springframework.orm.jpa.SharedEntityManagerCreator . 这个类维持在一个查找表EntityManager的方法flushmergepersistrefreshremove要求在事务中运行。因此,每当它遇到不在事务内的方法调用时,它就会退出。

注释@PersistenceContext有一个type属性,可以设置为PersistenceContextType.EXTENDED或 之一PersistenceContextType.TRANSACTION,后者是默认值。因此,默认@PersistenceContext导致SharedEntityManagerCreator查找事务并在找不到事务时退出。

使用PersistenceContextType.EXTENDED绕过了在获取时检查事务的需要EntityManager,因此代码应该可以工作。


flush 仍然无法在没有事务的情况下调用,因为 JPA 提供程序要求仅在事务上下文中调用它。