Spring Hibernate JPA - @Transactional 不插入数据 (Postgres)



我正在实现一个带有事务的服务层,所有配置都在Java配置中处理。 服务事务使用 JPA 存储库运行。 事务执行正常,SQL显示在日志中(如果我设置了休眠跟踪),但是没有数据插入数据库(Postgres)。 发生这种情况时,我什至没有收到异常。 解决此问题的最佳方法是什么? (简化的业务逻辑如下)

价值集服务.java

public interface ValueSetService {
    void processValueSets(List<Code> codes);
}

ValueSetServiceImpl.java

@Service
public class ValueSetServiceImpl implements ValueSetService {
    @Autowired
    private ValueSetRepository valueSetRepository;
    @Autowired
    private CodeRepository codeRepository;
    @Transactional
    public void processValueSets(List<Code> codes) 
    {
        for (Code code : codes)
        {
            codeRepository.save(code);
        }
    }
}

JpaConfig.java

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.package.repository")
@ComponentScan(basePackages = {"org.package.service"})
public class JpaConfig {
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager tm =
                new JpaTransactionManager();
        tm.setEntityManagerFactory(entityManagerFactory);
        // tm.setDataSource(dataSource());
        return tm;
    }
    @Bean
    public PersistenceExceptionTranslationPostProcessor persistenceManager() {
        return new PersistenceExceptionTranslationPostProcessor();
    }
    @Bean
    public PropertyOverrideConfigurer propertyOverrideConfigurer() {
        PropertyOverrideConfigurer config = new PropertyOverrideConfigurer();
        config.setIgnoreResourceNotFound(true);
        config.setLocation(new ClassPathResource("jpa.db.properties"));
        return config;
    }
    @Bean(destroyMethod = "shutdown")
    public HikariDataSource mainDataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        dataSource.setJdbcUrl("jdbc:postgresql://localhost/dbname");
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setMaximumPoolSize(20);
        return dataSource;
    }
    @Bean
    public LazyConnectionDataSourceProxy dataSource() {
        LazyConnectionDataSourceProxy dataSource = new LazyConnectionDataSourceProxy();
        dataSource.setTargetDataSource(mainDataSource());
        return dataSource;
    }
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setPersistenceUnitName("puName");
        em.setDataSource(dataSource);
        em.setPackagesToScan(new String[]{"org.package.model.**"});
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter
                .setDatabasePlatform("org.hibernate.dialect.PostgreSQL9Dialect");
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());
        return em;
    }
    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory entityManagerFactory) {
        HibernateJpaSessionFactoryBean sessionFactory = new HibernateJpaSessionFactoryBean();
        sessionFactory.setEntityManagerFactory(entityManagerFactory);
        return sessionFactory;
    }
    private Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect",
                "org.hibernate.dialect.PostgreSQL9Dialect");
        properties.setProperty("hibernate.generate_statistics", "false");
        properties.setProperty("hibernate.show_sql", "false");
        properties
                .setProperty("hibernate.cache.use_second_level_cache", "true");
        properties.setProperty("hibernate.cache.use_query_cache", "true");
        properties.setProperty("hibernate.current_session_context_class",
                "org.springframework.orm.hibernate4.SpringSessionContext");
        properties.setProperty("hibernate.id.new_generator_mappings", "true");
        properties.setProperty("hibernate.id.optimizer.pooled.prefer_lo",
                "true");
        properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");
        properties.setProperty("net.sf.ehcache.configurationResourceName", "/ehcache-model.xml");
        return properties;
    }
}

代码存储库.java

public interface CodeRepository extends JpaRepository<Code, Integer>, QueryDslPredicateExecutor<Code> {
}

代码.java

@Entity
@Table(name = "code", catalog = "dbname", schema = "application")
public class Code implements Cloneable, Serializable, IPojoGenEntity, ICode {
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "codeCode_idGenerator")
    @Basic( optional = false )
    @Column( name = "code_id", nullable = false  )
    @SequenceGenerator(allocationSize=1, name = "codeCode_idGenerator", sequenceName = "dbname.application.code_id_seq", schema = "application", catalog = "dbname")
    public Integer getId() {
        return this.id;
    }
    @ManyToOne( cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY )
    @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
    @Basic( optional = true )
    @JoinColumn(name = "value_set_id", nullable = true )
    public ValueSet getValueSet() {
        return this.valueSet;
    }
}

控制台中的休眠 SQL 输出示例

[28/04/2015 14:24:15] DEBUG  insert into dbname.application.code (code_name, code_system_id, date_created, date_disabled, date_updated, description, user_created, user_updated, value_set_id, code_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) (SQL)
Hibernate: insert into dbname.application.code (code_name, code_system_id, date_created, date_disabled, date_updated, description, user_created, user_updated, value_set_id, code_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
[28/04/2015 14:24:15] TRACE  binding parameter [1] as [VARCHAR] - [447422004] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [2] as [INTEGER] - [39] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [3] as [TIMESTAMP] - [Tue Apr 28 14:24:15 EDT 2015] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [4] as [TIMESTAMP] - [null] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [5] as [TIMESTAMP] - [Tue Apr 28 14:24:15 EDT 2015] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [6] as [VARCHAR] - [Code name goes here] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [7] as [INTEGER] - [null] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [8] as [INTEGER] - [null] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [9] as [INTEGER] - [666] (BasicBinder)
[28/04/2015 14:24:15] TRACE  binding parameter [10] as [INTEGER] - [67310] (BasicBinder)

尝试添加 tm.afterPropertiesSet(); 如下所示或在 JpaTransactionManager 的构造函数中注入 entityManagerFactory。

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager tm = new JpaTransactionManager();
    tm.setEntityManagerFactory(entityManagerFactory);
    tm.afterPropertiesSet();
    return tm;
}

该问题是由数据异常值引起的,该异常值在运行时基本上填满了事务日志(导致应用程序基本上停止)。 重构流程以提高性能。