【问题标题】:Failed to retrieve PlatformTransactionManager for @Transactional test for test context无法为测试上下文的 @Transactional 测试检索 PlatformTransactionManager
【发布时间】:2016-09-17 14:06:50
【问题描述】:

当尝试在事务之间测试 Hibernate(版本 4)EHCache 的缓存功能时 - 它失败了:Failed to retrieve PlatformTransactionManager for @Transactional test for test context

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ApplicationConfig.class, CachingConfig.class }, loader = AnnotationConfigContextLoader.class)
@PersistenceContext
@Transactional
public class EHCacheTest extends AbstractTransactionalJUnit4SpringContextTests {
    @Autowired
    private SessionFactory sessionFactory;
@Test
    public void testTransactionCaching(){
        Session session = sessionFactory.getCurrentSession();
        System.out.println(session.get(CustomerEntity.class, 1));
        Query query = session.createQuery("from CustomerEntity where CustomerEntity.customerId<10").setCacheable(true).setCacheRegion("customer");
        @SuppressWarnings("unchecked")
        List<CustomerEntity> customerEntities = query.list();
        System.out.println(customerEntities);

        TestTransaction.flagForCommit();
        TestTransaction.end();

        TestTransaction.start();

        Session sessionNew =  sessionFactory.getCurrentSession();
        System.out.println(sessionNew.get(CustomerEntity.class, 1));
        Query anotherQuery = sessionNew.createQuery("from CustomerEntity where CustomerEntity.customerId<10");
        anotherQuery.setCacheable(true).setCacheRegion("customer");
        @SuppressWarnings("unchecked")
        List<CustomerEntity> customerListfromCache = anotherQuery.list();
        System.out.println(customerListfromCache);

        TestTransaction.flagForCommit();
        TestTransaction.end();
    }
}

手动编程事务处理是按照 Spring 4.x 在documentation 中建议的方式实现的。

应用配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories (basePackages = { "com.hibernate.query.performance.persistence" }, transactionManagerRef = "jpaTransactionManager")
@EnableJpaAuditing
@PropertySource({ "classpath:persistence-postgresql.properties" })
@ComponentScan({ "com.hibernate.query.performance.persistence" })
public class ApplicationConfig {

    @Autowired
    private Environment env;

    public ApplicationConfig() {
        super();
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(applicationDataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());

        return sessionFactory;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(applicationDataSource());
        emf.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });

        final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        emf.setJpaVendorAdapter(vendorAdapter);
        emf.setJpaProperties(hibernateProperties());

        return emf;
    }

    @Bean
    public DataSource applicationDataSource() {
        final BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
        dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
        dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
        dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));

        return dataSource;
    }

    @Bean
    public PlatformTransactionManager hibernateTransactionManager() { // TODO: Really need this?
        final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }

    @Bean
    public PlatformTransactionManager jpaTransactionManager() { // TODO: Really need this?
        final JpaTransactionManager transactionManager = new JpaTransactionManager(); // http://stackoverflow.com/questions/26562787/hibernateexception-couldnt-obtain-transaction-synchronized-session-for-current
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    private final Properties hibernateProperties() {
        final Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));

        hibernateProperties.setProperty("hibernate.show_sql", "true");
        hibernateProperties.setProperty("hibernate.format_sql", "true");
        // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
        hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");

        // Envers properties
        hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); // TODO: Really need this?

        return hibernateProperties;
    }
}

缓存配置

@Configuration
@EnableCaching
public class CachingConfig implements CachingConfigurer {
    @Bean(destroyMethod="shutdown")
    public net.sf.ehcache.CacheManager ehCacheManager() {
        CacheConfiguration cacheConfiguration = new CacheConfiguration();
        cacheConfiguration.setName("myCacheName");
        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
        cacheConfiguration.setMaxElementsInMemory(1000);

        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
        config.addCache(cacheConfiguration);

        return net.sf.ehcache.CacheManager.create(config);
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheManager());
    }

    @Override
    public CacheResolver cacheResolver() {
        return null;
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Override
    public CacheErrorHandler errorHandler() {
        return null;
    }
}

错误

java.lang.IllegalStateException: Failed to retrieve PlatformTransactionManager for @Transactional test for test context [DefaultTestContext@d8355a8 testClass = EHCacheTest, testInstance = com.hibernate.query.performance.EHCacheTest@3532ec19, testMethod = testTransactionCaching@EHCacheTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@59fa1d9b testClass = EHCacheTest, locations = '{}', classes = '{class com.hibernate.query.performance.config.ApplicationConfig, class com.hibernate.query.performance.config.CachingConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.AnnotationConfigContextLoader', parent = [null]]].

如何让它发挥作用?


更新:

通过添加使其工作,但不确定是否真的需要 @TestExecutionListeners

@Transactional(transactionManager = "hibernateTransactionManager")
@TestExecutionListeners({})

【问题讨论】:

    标签: java spring hibernate junit transactions


    【解决方案1】:

    我遇到了同样的问题,我把它解决了:

    添加到我的配置文件

    @Configuration
    @EnableTransactionManagement // +++ added annotation
    @EnableJpaRepositories(basePackages = "com.stackoverflow.my.project")
    @PropertySource("application-tests.properties")
    @ComponentScan({ "com.stackoverflow.my.project" })
    public class H2JpaConfig {
    
    @Bean
        public PlatformTransactionManager transactionManager() {
            final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
            transactionManager.setSessionFactory(sessionFactory().getObject());
            return transactionManager;
        }
    }
    

    并添加我的测试类:

    @ContextConfiguration(classes = { H2JpaConfig.class })
    @RunWith(SpringJUnit4ClassRunner.class)
    @Transactional("transactionManager") // +++ add transaction manager
    public class MyDaoClassTest extends AbstractTransactionalJUnit4SpringContextTests { // +++ extends AbstractTransactionalJUnit4SpringContextTests 
        @Autowired
        private MyDaoClass myDaoClass;
    }
    

    它对我来说很好用。 感谢阅读

    【讨论】:

      【解决方案2】:

      正如answered by ekem chitsiga 一样,正确的解决方案是定义一个事务管理器。但是,您可以使用@Transactional(propagation = Propagation.NOT_SUPPORTED) 解决此问题。这将导致TransactionalTestExecutionListener 不需要事务管理器,但这样做的结果是您的测试实际上不是事务性的,因此您应该问为什么它甚至被这样注释。

      【讨论】:

        【解决方案3】:

        @Transactional 如果未明确指定,则在您的应用程序上下文中需要一个名为 transactionManager 的 bean。使用 @Transaction 注释值属性指定要用于测试的事务管理器

        例如,如果您想使用 hibernateTransactionManager,请将此指定为

        @RunWith(SpringJUnit4ClassRunner.class)
        @ContextConfiguration(classes = { ApplicationConfig.class, CachingConfig.class }, loader = AnnotationConfigContextLoader.class)
        @PersistenceContext
        @Transactional("hibernateTransactionManager")
        public class EHCacheTest extends AbstractTransactionalJUnit4SpringContextTests {
        }
        

        否则将要使用的事务管理器重命名为默认名称 transactionManager

        @Bean
            public PlatformTransactionManager transactionManager() { // TODO: Really need this?
                final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
                transactionManager.setSessionFactory(sessionFactory().getObject());
                return transactionManager;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-05
          • 2013-08-25
          • 1970-01-01
          • 2020-01-23
          • 1970-01-01
          • 2021-12-16
          • 2015-01-24
          • 1970-01-01
          相关资源
          最近更新 更多