Spring Transactional并不使用EntityManager持久化实体,而是使用Spring Data

时间:2017-07-18 20:18:37

标签: java spring hibernate jpa spring-transactions

也许这种情况太常见但仍然存在。

我有一个小测试项目,我正在测试所有JPA的东西。我几乎在任何地方使用Spring Data和JPA存储库都可以正常工作。但现在我试图让我的服务来保存实体。该服务看起来像这样:

@Service
public class SomeServiceImpl implements SomeService {
    @Autowired
    private EntityManagerFactory entityManagerFactory;

    public SomeServiceImpl(EntityManagerFactory entityManagerFactory) {
        this.entityManagerFactory = entityManagerFactory;
    }

    @Override
    @Transactional
    public SomeEntity save(SomeEntity someEntity) {
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.persist(someEntity);

        return someEntity;
}

持久性配置看起来像这样(我故意复制和粘贴整个配置。也许它会帮助你重现错误):

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
@PropertySource({"classpath:conf/application.properties"})
public class PersistenceConfig {
    @Autowired
    private Environment environment;

    @Bean
    public DataSource dataSource() throws SQLException {
        PoolDataSourceImpl dataSource = new PoolDataSourceImpl();
        dataSource.setConnectionFactoryClassName(environment.getRequiredProperty("db.driverClassName"));
        dataSource.setURL(environment.getRequiredProperty("db.url"));
        dataSource.setUser(environment.getRequiredProperty("db.username"));
        dataSource.setPassword(environment.getRequiredProperty("db.password"));
        dataSource.setFastConnectionFailoverEnabled(
                Boolean.valueOf(environment.getRequiredProperty("db.fast.connect.failover.enabled")));
        dataSource.setValidateConnectionOnBorrow(true);
        dataSource.setSQLForValidateConnection("SELECT SYSDATE FROM DUAL");
        dataSource.setONSConfiguration(environment.getRequiredProperty("db.ons.config"));
        dataSource.setInitialPoolSize(Integer.valueOf(environment.getRequiredProperty("db.initial.pool.size")));
        dataSource.setMinPoolSize(Integer.valueOf(environment.getRequiredProperty("db.min.pool.size")));
        dataSource.setMaxPoolSize(Integer.valueOf(environment.getRequiredProperty("db.max.pool.size")));
        dataSource.setAbandonedConnectionTimeout(0);
        dataSource.setInactiveConnectionTimeout(60 * 25);
        dataSource.setTimeToLiveConnectionTimeout(0);
        dataSource.setMaxConnectionReuseTime(60 * 30L);

        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.setProperty("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.setProperty("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        properties.setProperty("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));

        return properties;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Autowired DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setPackagesToScan("com.dropbinc.learning.jpa.model");

        JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
        Map jpaProperties = new HashMap();
        jpaProperties.put("javax.persistence.schema-generation.database.action", "drop-and-create");
        entityManagerFactory.setJpaPropertyMap(jpaProperties);
        entityManagerFactory.setJpaProperties(hibernateProperties());

        return entityManagerFactory;
    }

    @Bean
    public PlatformTransactionManager transactionManager(@Autowired EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);

        return transactionManager;
    }

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

还有一个我计划配置应用程序的其余部分(放在同一个包中):

@Configuration
@ComponentScan(basePackages = "com.dropbinc.learning.jpa")
public class AppConfig {
}

我试图调试Spring但是我无法检测到JPA存储库的事务行为与我的服务之间的区别。我看到交易已经创建甚至提交。但是在JPA存储库的情况下它被保存了,而在我的服务实现中它确实生成了id,但实体并没有出现在数据库中。

我在测试中运行所有内容,通过接口自动启动服务:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { AppConfig.class, PersistenceConfig.class })
public class AllTheTests {
    @Autowired
    SomeService someService;

    ...
}

非常感谢您的任何建议!

编辑添加entityManager.flush()来电会产生nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress

0 个答案:

没有答案