2016-06-14 134 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方法)。