2016-06-14 3 views
10

스프링 배치 및 데이터 jpa 프로젝트와 함께 스프링 부트 프로젝트를 통합하려고합니다. 작업 및 데이터 구성과 관련된 모든 내용은 필자의 작업 작성자 결과를 데이터베이스에 유지하는 것 외에는 옳습니다. 내가 파일을 읽고 그것을 처리 한 후에, 나는 그것을 mysql 데이터베이스에 쓸 수 없다. 오류는 없지만 삽입 할 필요는 없습니다. 흥미로운 점은 내 데이터 소스가 구성되어 있다는 것입니다. 삽입하기 전에 데이터베이스에서 샘플 레코드를 가져올 수 있습니다.이 문제를 해결하는 데 도움이됩니다.스프링 배치 및 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(); 
} 

다오 클래스 :

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

} 
,536,

tempPerson은 jpa 데이터를 테스트하기위한 개체입니다. 그것은 데이터베이스에서 id 1 인 사람 객체를 가져 오지만 다음 줄에는 오류없이 데이터베이스에 삽입되지 않습니다. 그냥 줄을 실행하고 루프를 계속합니다.

+0

나는 비슷한 문제에 직면하고있다. 이 질문에 대한 업데이트가 있습니까? – balteo

+2

스프링 배치에 대해서는 아무 것도 모르지만 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 Bean은 그 이름을 가진 Bean을 찾지 않으면 Spring Boot가 자동으로 구성합니다. - 귀하의 데이터베이스 트랜잭션은 Resourceless 트랜잭션을 거칩니다.

당신은이를 건너 뛸 수 있습니다 :

@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

나는 그것을 놓쳤을 수도 있지만 사용중인 DB 액세스 방법 (JPA, Hibernate, JDBC 등)을 어디에 지정했는지는 알 수 없습니다. 나는 JPA를 추측하고 있지만 ItemWriter가 DB 인식 ItemWriter (RepositoryItemWriter, JpaItemWriter, JdbcBatchItemWriter, HibernateItemWriter) 중 하나를 확장해야한다고 생각합니다. 기본 ItemWriter는 트랜잭션과 모든 자원을 직접 관리 할 것을 기대합니다. 대신 RepositoryItemWriter (또는 적절한 방법)를 사용해보십시오. EntityManager를 제공하고 트랜잭션 내에서 쓰기가 호출되어야합니다 (예 : @Transactional 일부 메소드).

관련 문제