2016-06-14 69 views
10

我正在将spring引导项目与spring批处理和数据jpa项目集成。所有与作业和数据配置相关的东西都是正确的,除此之外,我的作业写入器会保留在数据库中。在我读取一个文件并处理它之后,我无法将它写入mysql数据库。没有错误,但没有插入。有趣的是我的数据源被配置。因为在插入之前,我可以从数据库中获取样本记录。请帮助我解决这个问题。弹簧引导集成spring批处理和jpa

我application.properties:

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(); 
} 

DAO类:

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个人对象,但下一行没有插入数据库而没有错误。只是执行该行并继续循环。

+0

我正面临类似的问题。有关这个问题的任何更新? – balteo

+2

我对Spring批处理一无所知,但使用ResourceLessTransactionManager和MapJobRepositoryFactory记录为“用于内存中的持久性和测试目的”(http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/ #inMemoryRepository)。尝试使用JPA事务管理器和一个真正的JobRepository。 –

+0

你说得对,我应该更仔细地阅读这篇文章。因此我的问题是不同的。我在这里包括它:http://stackoverflow.com/questions/38287298 – balteo

回答

4

此问题的解决方案可能比预期的更接近。你只是试图改变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 - 并且你的数据库事务正在经历一个无穷无尽的事务)。

您也可以跳过此:

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

,并直接调用豆(只是要“更加确信”,适当的事务管理器使用批次):

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

让我知道当你测试它,我希望它是主要问题:)

4

我可能错过了它,但我没有看到你指定了什么地方使用的数据库访问方法(JPA,Hibernate,JDBC等)。我假设JPA,但是我认为你的ItemWriter需要扩展一个DB-aware ItemWriters(RepositoryItemWriter,JpaItemWriter,JdbcBatchItemWriter,HibernateItemWriter)。基础ItemWriter希望您自己管理事务和所有资源。请尝试使用RepositoryItemWriter(或其中合适的)。您可能必须提供一个EntityManager并确保从事务内部调用写入(例如,某种@Transactional方法)。

相关问题