【问题标题】:Spring boot integration with spring batch and jpaSpring Boot 与 Spring Batch 和 JPA 的集成
【发布时间】:2023-03-12 16:35:02
【问题描述】:

我正在将 Spring Boot 项目与 Spring Batch 和 Data JPA 项目集成。与作业和数据配置相关的所有内容都是正确的,除了将我的作业编写器结果保存在数据库中。在我读取一个文件并处理它之后,我无法将它写入 mysql 数据库。没有错误,但也没有插入。有趣的是我的数据源已配置。因为在插入之前,我可以从数据库中获取示例记录。请帮助我解决这个问题。

我的应用程序属性:

spring.datasource.url = jdbc:mysql://localhost:3306/batchtest?  characterEncoding=UTF-8&autoReconnect=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

批量配置:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;

@Bean
public ResourcelessTransactionManager transactionManager() {
    return new ResourcelessTransactionManager();
}

@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
    MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager);
    mapJobRepositoryFactoryBean.setTransactionManager(transactionManager);
    return mapJobRepositoryFactoryBean.getObject();
}

@Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
    SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
    simpleJobLauncher.setJobRepository(jobRepository);
    return simpleJobLauncher;
}
@Bean
public FlatFileItemReader<Person> reader() {
    FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
    reader.setResource(new ClassPathResource("sample-data.csv"));
    reader.setLineMapper(new DefaultLineMapper<Person>() {{
        setLineTokenizer(new DelimitedLineTokenizer() {{
            setNames(new String[] { "firstName", "lastName" });
        }});
        setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
            setTargetType(Person.class);
        }});
    }});
    return reader;
}
@Bean
public PersonItemProcessor processor() {
    return new PersonItemProcessor();
}
@Bean
public ItemWriter<Person> writer() throws Exception {
    return new PersonWriter();
}
@Bean
public Job importUserJob() throws Exception{
    return jobBuilderFactory.get("importUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();
}
 @Bean
public Step step1() throws Exception{
    return stepBuilderFactory.get("step1")
            .<Person, Person> chunk(1)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
}

道类:

public interface PersonDao extends CrudRepository<Person,Integer> {
}

作家类:

public class PersonWriter implements ItemWriter<Person> {
@Autowired
PersonDao personDao;

@Override
public void write(List<? extends Person> items) throws Exception {
    LOGGER.info("Received the information of {} students", items.size());
    for(Person person:items)
    {
        LOGGER.info(String.format("inserting for customre %s %s", person.getFirstName(), person.getLastName()));
        Person tempPerson = personDao.findOne(1);
        personDao.save(person) ;
        LOGGER.info(String.format("person id : %d",person.getId()));
    }

}

tempPerson 是一个用于测试 jpa 数据的对象。它从数据库中获取具有 id 1 的人员对象,但下一行没有插入数据库而没有错误。只是执行该行并继续循环。

【问题讨论】:

  • 我面临着类似的问题。这个问题有更新吗?
  • 我对 Spring 批处理一无所知,但使用 ResourceLessTransactionManager 和 MapJobRepositoryFactory 被记录为“用于内存持久性和测试目的”(docs.spring.io/spring-batch/trunk/reference/htmlsingle/…)。尝试使用 JPA 事务管理器和真正的 JobRepository。
  • 你说得对,我应该更仔细地阅读帖子。因此,我的问题有所不同。我在这里包括它:stackoverflow.com/questions/38287298

标签: spring spring-boot spring-data spring-batch


【解决方案1】:

这个问题的解决方案可能比预期的更接近。您是否只是尝试更改 transactionManager bean 的名称? Spring Data JPA 默认不会使用不同的名称。

我重现了你的问题,然后我只是从这个切换:

@Bean
public ResourcelessTransactionManager transactionManager() {
    return new ResourcelessTransactionManager();
}

到这里:

@Bean
public ResourcelessTransactionManager resourcelessTransactionManager() {
    return new ResourcelessTransactionManager();
}

在我看来,这解决了问题。请记住,“transactionManager”是 Spring Data JPA 中 transactionManager 的默认 bean 名称(至少据我所知,Spring Boot 会自动配置它,除非它找到具有该名称的 Bean,如果找到了,它会使用找到的那个--并且您的数据库事务正在经历无资源的事务)。

你也可以跳过这个:

@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
    return new MapJobRepositoryFactoryBean(transactionManager).getObject();
}

并直接调用 bean(只是为了“更确定”正确的事务管理器与 Batch 一起使用):

@Bean
public JobRepository jobRepository() throws Exception {
    return new MapJobRepositoryFactoryBean(resourcelessTransactionManager()).getObject();
}

当你测试它时告诉我,我希望这是主要问题:)

【讨论】:

    【解决方案2】:

    我可能错过了它,但我没有看到您在哪里指定您正在使用的数据库访问方法(JPA、Hibernate、JDBC 等)。我假设为 JPA,但我认为您的 ItemWriter 需要扩展其中一个支持 DB 的 ItemWriter(RepositoryItemWriterJpaItemWriterJdbcBatchItemWriterHibernateItemWriter)。基础 ItemWriter 期望您自己管理事务和所有资源。尝试改用 RepositoryItemWriter (或任何合适的)。您可能必须提供一个 EntityManager 并确保从事务中调用 write(例如一些 @Transactional 方法)。

    【讨论】:

      猜你喜欢
      • 2018-07-10
      • 2017-09-22
      • 2018-07-02
      • 2015-02-27
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 2012-10-20
      相关资源
      最近更新 更多