如何在春季批处理中使用HibernateCursorItemReader

时间:2019-07-15 15:53:51

标签: java spring spring-batch

在spring批处理作业中,我有一个步骤,我想使用Hibernate从数据库中按块读取数据,进行处理并将其写回到数据库中。现在我在设置阅读器时遇到了一些麻烦:

@EnableBatchProcessing
@Configuration
@ComponentScan(basePackages = {"com.x.y.z.database", "com.x.y.p.database"}, excludeFilters={
        @ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE, value=ConfigHelperMail.class)})
@EntityScan(basePackages = {"com.x.y.z.database", "com.x.y.p.database"})
@EnableJpaRepositories({"com.x.y.z.database", "com.x.y.p.database"})
public class BatchConfiguration {
    @Autowired
    public JobBuilderFactory jobs;
    @Bean
    public Job job(CustomJobListener listener,
                     @Qualifier("step1") Step step1,
                     @Qualifier("step2") Step step2,
                     @Qualifier("step3") Step step3) {
        return jobs.get("SimpleJobName")
                .incrementer(new RunIdIncrementer())
                .preventRestart()
                .listener(listener)
                .start(step1)
                .next(step2)
                .next(step3)
                .build();
    }
}

step1编写器中,我使用Hibernate将数据保存到数据库中:

@Entity
@Table(name = "tmp_z_stepone")
public class StepOneEntity {
    @Id
    @Column(name = "reference")
    private String reference;
    /** Other properties and getters and setters **/
}

@Component
public class StepOneWriter implements ItemWriter<StepOneEntity> {
    @Autowired
    private StepOneService stepOneService;
    @Override
    public void write (List<? extends StepOneEntity> items) throws WriterException {
        stepOneService.saveMany(items);
    }
}

StepOneService带有@Service注释,它使用扩展了CrudRepository<StepOneEntity, String>的DAO接口,其saveMany方法仅使用{{1 }}。

第2步

save

我认为我正在对一些会话/ ORM配置进行任务,但是我不知道在哪里,错误如下:

CrudRepository<StepOneEntity, String>

2 个答案:

答案 0 :(得分:1)

HibernateCursorItemReader实现了InitializingBean接口,这意味着如果将Spring声明为bean,它将在容器初始化时调用其afterPropertiesSet。但是,在您的情况下,HibernateCursorItemReader在应用程序上下文中未声明为Bean,而是包装在一个类(StepTwoReader)中,然后使用reader.read()创建。

如果使用HibernateCursorItemReader方法中的当前代码将read声明为bean,则应该获得一个IllegalStateException并显示消息:“必须提供SessionFactory”。实际上,您实际上需要为Hibernate阅读器配置SessionFactory

另一种选择是使用HibernateCursorItemReaderBuilder,以确保正确配置阅读器。

答案 1 :(得分:1)

@StepScope
@Slf4j
@Component
public class CursorItemReader extends HibernateCursorItemReader<ItemEntity> {


    public CursorItemReader(EntityManagerFactory entityManagerFactory,
                            @Value("#{stepExecution}")StepExecution stepExecution) {

       
        this.setName("CursorItemReader");
        this.setSessionFactory(entityManagerFactory.createEntityManager().unwrap(org.hibernate.Session.class).getSessionFactory());
        this.setQueryString("from ItemEntity");
        this.setUseStatelessSession(true);
        this.setFetchSize(5);
    }

    @Override
    public ItemEntity read() throws Exception {
        ItemEntity item = this.doRead();
        return item;
    }

}

您也可以参考- https://docs.spring.io/spring-batch/docs/current/reference/html/readersAndWriters.html#HibernateCursorItemReader