java - JpaItemWriter : no transaction is in progress

标签 java spring jpa spring-batch

我想使用 JpaItemWriter 来批处理持久实体。但是当我使用下面的代码进行持久化时,我被告知:

Hibernate: 
    select
        nextval ('hibernate_sequence')
[] 2014-03-19 15:46:02,237 ERROR : TransactionRequiredException: no transaction is in progress

如何启用以下交易:

@Bean
public ItemWriter<T> writer() {
    JpaItemWriter<T> itemWriter = new JpaItemWriter<>();
    itemWriter.setEntityManagerFactory(emf);
}

@Configuration
@EnableTransactionManagement
@EnableBatchProcessing 
class Config{ {
     @Bean
    public LocalContainerEntityManagerFactoryBean emf() {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource());
        emf.setPackagesToScan("my.package");
        emf.setJpaVendorAdapter(jpaAdapter());
        emf.setJpaProperties(jpaProterties());
        return emf;
}

编辑:

@Bean
public Job airlineJob(JobBuilderFactory jobs, Step step) {
    return jobs.get("job")
            .start(step)
            .build();
}

//Reader is a `FlatFileItemReader`, writer is `CustomItemWriter`.
@Bean
public Step step(StepBuilderFactory steps,
        MultiResourceItemReader<T> rea,
        ItemProcessor<T, T> pro,
        ItemWriter<T> wr) {
    return steps.get("step")
            .reader(rea)
            .processor(proc)
            .writer(wr)
            .build();
}

//use same datasource and tx manager as in the full web application
@Bean
public JobLauncher launcher(TransactionManager tx, DataSource ds) throws Exception {
    SimpleJobLauncher launcher = new SimpleJobLauncher();

    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(ds);
    factory.setTransactionManager(tx);

    jobLauncher.setJobRepository(factory.getJobRepository());
    return launcher;
}

编辑 2 作为对@Haim 的回应:

@Bean
    public JpaItemWriter<T> jpaItemWriter(EntityManagerFactory emf) {
        JpaItemWriter<T> writer = new JpaItemWriter<T>();
        writer.setEntityManagerFactory(emf);
        return writer;
    }

最佳答案

我同意 Michael Minella 的观点:Spring Batch 作业存储库不喜欢与其他人共享其事务管理器。逻辑很简单,如果您在步骤失败时与您的步骤事务管理器共享您的作业事务管理器,它将回滚步骤和写入作业存储库的数据。这意味着您不会为作业重启保留数据。 为了使用两个事务管理器,您需要:

删除@EnableTransactionManagement,以防你为上面的@Transactional 使用它
定义一个额外的事务管理器

@Bean
@Qualifier("jpaTrx")
public PlatformTransactionManager jpaTransactionManager() {
       return new JpaTransactionManager(emf());
}

根据您的步骤设置事务管理器

@Autowired
@Qualifier("jpaTrx")
PlatformTransactionManager jpaTransactionManager

 //Reader is a FlatFileItemReader, writer is CustomItemWriter.
    @Bean
    public Step step(StepBuilderFactory steps,
            MultiResourceItemReader<T> rea,
            ItemProcessor<T, T> pro,
            ItemWriter<T> wr) {
        return steps.get("step")
                //attach tx manager
                .transactionManager(jpaTransactionManager)
                .reader(rea)
                .processor(proc)
                .writer(wr)
                .build();
    }

关于java - JpaItemWriter : no transaction is in progress,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22509529/

相关文章:

java - 如何制作具有以下签名 '(x OR y) AND z'的spring data自定义查询方法

javax.comm 以及如何修复 java.lang.NoClassDefFoundError

数据库支持缓存的 Java 解决方案

java - 如何指定 Jackson 仅使用字段 - 最好是全局的

java - 如何在 spring jpa 中检查日期不为空

java - 从 Spring Controller 中删除重复项

java - @SequenceGenerator 与 DerbyEmbedded 问题

java - 使用 ASM 5.0 的字节码检测。注入(inject)跟踪器来跟踪局部变量

java - 多线程(多请求)调用的Spring @Transactional方法

java - 如何在 JPA 中创建成对列表作为参数?