具有多个JPA持久性单元的Spring注释配置不会持续存在

时间:2017-06-13 14:55:40

标签: java spring hibernate jpa spring-transactions

我从this guide开始,将我们的xml配置迁移到注释配置。

当前的问题是,我的测试持久化似乎并没有实际写入数据(=没有事务提交)。这导致下一次检查失败。环境目前有五个持久性单元,并且根据entityManagerFactories和transactionManagers。

MyTest.java

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {PersistenceJPAConfig.class}, loader = AnnotationConfigContextLoader.class)
public class MyTest {

    @Autowired
    private MyDao testable;

    @Transactional(transactionManager = "tm1") // tried with name= and without
    @Test
    public void crudTest() throws Exception {
        // assert that the table is empty
        List<MyDO> all = testable.getAll();
        assertTrue(all.isEmpty());

        // write one entity
        MyDO anEntity = new MyDO();
        testable.persist(anEntity);

        // load all entities and assert that the details match
        List<MyDO> allAfterInsert = testable.getAll();
        // THIS FAILS
        assertFalse("The database result should not be empty.", allAfterInsert.isEmpty());
    }
}

PersistenceJPAConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan("my.package")
public class PersistenceJPAConfig {

    @PersistenceContext(unitName = "myPersistenceUnit") // also tried 
    @Bean(name = "myEntityManager")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] {"my.package"});
        em.setPersistenceUnitName("myPersistenceUnit");

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    // ... the same for the other persistenceUnits with increasing names

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        return dataSource;
    }


    @Bean(name = "tm1")
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getNativeEntityManagerFactory());
        transactionManager.setPersistenceUnitName("myPersistenceUnit");
        transactionManager.afterPropertiesSet();
        return transactionManager;
    }

    // ... the same for the other persistenceUnits with increasing names

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

    @Bean
    public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
        return new PersistenceAnnotationBeanPostProcessor();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        return properties;
    }
}

MyDao.java

public class MyDao {

    @PersistenceContext(unitName = "myPersistenceUnit")
    EntityManager em;

    @Override
    @Transactional(transactionManager = "tm1") // also tried with different variations like above
    public Long persist(final MyDO entity) {
        em.persist(entity); // tried to add an em.flush(), but that throws a TransactionRequiredException: no transaction is in progress
        // handling transactions would throw IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
        return entity.getId();
    }
}

持久性单元位于文件META-INF/persistence.xml

测试使用xml配置,但不能使用我当前的注释配置。我忘记了什么吗?我可以提供哪些更多信息?

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案:我使用entityManagerFactory().getNativeEntityManagerFactory()而不是entityManagerFactory().getObject(),而且一切都按预期工作。

@Bean(name = "tm1")
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    transactionManager.setPersistenceUnitName("myPersistenceUnit");
    transactionManager.afterPropertiesSet();
    return transactionManager;
}

我不确定为什么。