2016-06-14 7 views
10

Ich integriere ein Spring Boot-Projekt mit einer Feder Batch-und Daten-Jpa-Projekt. Alles, was mit der Job- und Datenkonfiguration zu tun hat, ist richtig, außer dass mein Jobwriter in der Datenbank bleibt. nachdem ich eine datei gelesen und verarbeitet habe, kann ich sie nicht in die mysql datenbank schreiben. Es gibt keinen Fehler, aber auch kein Einfügen. Interessant ist, dass meine Datenquelle konfiguriert ist. Weil ich vor dem Einfügen einen Beispieldatensatz aus der Datenbank holen kann. Bitte helfen Sie mir, dieses Problem zu lösen.Spring Boot Integration mit Spring Batch und Jpa

mein 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 

Batch-Konfiguration:

@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 Klasse:

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

Schriftsteller Klasse:

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 ist ein Objekt zum Testen der jpa-Daten. Es ruft ein Personenobjekt mit ID 1 aus der Datenbank, aber nächste Zeile gibt es kein Einfügen in die Datenbank ohne Fehler. einfach die Linie ausführen und die Schleife fortsetzen.

+0

Ich stehe vor einem ähnlichen Problem. Irgendwelche Updates zu dieser Frage? – balteo

+2

Ich weiß nichts über Spring-Batch, aber die Verwendung eines ResourceLessTransactionManager und einer MapJobRepositoryFactory ist dokumentiert als "für In-Memory-Persistenz und Testzwecke" (http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/ #inMemoryRepository). Verwenden Sie einen JPA-Transaktionsmanager und ein echtes JobRepository. –

+0

Sie haben recht, ich hätte die Post sorgfältiger lesen sollen. Mein Problem ist daher anders. Ich schließe es hier ein: http://stackoverflow.com/questions/38287298 – balteo

Antwort

4

Eine Lösung für dieses Problem kann näher als erwartet sein. Haben Sie einfach versucht, den Namen der transactionManager-Bean zu ändern? Mit einem anderen Namen wird Spring Data JPA nicht standardmäßig verwendet.

reproduzierte ich Ihr Problem und dann schaltete ich einfach aus diesem:

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

dazu:

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

Und meiner Meinung nach, dass das Problem gelöst. Denken Sie daran, dass "transactionManager" der Standard-Bean-Name für transactionManager in Spring Data JPA ist (zumindest soweit ich weiß, dass Spring Boot es automatisch konfiguriert, sofern es kein Bean mit diesem Namen findet, und falls ja, verwendet es das gefundene - und Ihre Datenbanktransaktionen werden durch eine Ressource ausgeführt.

Sie können auch diese überspringen:

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

und die Bohne direkt anrufen (nur ‚sicherer‘ zu sein, dass die richtige Transaction Manager mit Batch verwendet wird):

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

Lassen Sie mich wissen wenn Sie es testen, und ich hoffe, dass es das Hauptproblem war :)

4

Ich habe es vielleicht verpasst, aber ich sehe nicht, wo Sie angeben, welche DB-Zugriffsmethode Sie verwenden (JPA, Hibernate, JDBC, etc.). Ich nehme JPA an, aber ich denke, Ihr ItemWriter muss einen der DB-fähigen ItemWriter erweitern (RepositoryItemWriter, JpaItemWriter, JdbcBatchItemWriter, HibernateItemWriter). Die Base ItemWriter erwartet von Ihnen, dass Sie die Transaktion und alle Ressourcen selbst verwalten. Versuchen Sie es stattdessen mit RepositoryItemWriter (oder was immer passend ist). Möglicherweise müssen Sie einen EntityManager bereitstellen und sicherstellen, dass der Schreibvorgang von einer Transaktion aus aufgerufen wird (z. B. eine @Transactional-Methode).