web-dev-qa-db-fra.com

Intégration de Spring Boot avec Spring Batch et JPA

J'intègre un projet Spring Boot avec un projet Spring batch et Data JPA. Toutes les choses liées à la configuration des travaux et des données sont correctes, sauf la persistance de mon résultat dans la base de données. après avoir lu un fichier et le traiter, je ne peux pas l'écrire dans la base de données mysql. Il n'y a pas d'erreur mais pas d'insertion aussi. chose intéressante est ma source de données est configurée. car avant l'insertion, je peux récupérer un exemple d'enregistrement dans la base de données. veuillez m'aider à résoudre ce problème.

mon 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 par lots:

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

Cours de Dao:

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

classe d'écrivain:

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 est un objet pour tester les données jpa. il récupère un objet personne avec id 1 à partir de la base de données, mais à la ligne suivante, il n'y a pas d'insertion dans la base de données sans erreur. il suffit d'exécuter la ligne et de continuer la boucle.

14
kaveh.n

Une solution à ce problème peut être plus proche que prévu. Avez-vous simplement essayé de changer le nom du bean transactionManager? Avec un nom différent, il ne sera pas utilisé par défaut par Spring Data JPA.

J'ai reproduit votre problème et je suis simplement passé de ceci:

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

pour ça:

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

Et à mon avis, cela a résolu le problème. Rappelez-vous que "transactionManager" est le nom de bean par défaut pour transactionManager dans Spring Data JPA (au moins pour autant que je comprends, Spring Boot le configure automatiquement à moins qu'il ne trouve un bean avec ce nom, et s'il le fait, il utilise celui trouvé - et vos transactions de base de données passent par une ressource sans ressources).

Vous pouvez également ignorer ceci:

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

et appeler le bean directement (juste pour être "plus sûr" que le bon gestionnaire de transactions est utilisé avec Batch):

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

Faites-moi savoir quand vous le testez, et j'espère que c'était le principal problème :)

4
patrykos91

Je l'ai peut-être manqué, mais je ne vois pas où vous spécifiez la méthode d'accès à la base de données que vous utilisez (JPA, Hibernate, JDBC, etc.). Je suppose JPA, mais je pense que votre ItemWriter doit étendre l'un des ItemWriters compatibles DB ( RepositoryItemWriter , JpaItemWriter , JdbcBatchItemWriter , - HibernateItemWriter ). Le ItemWriter de base attend de vous que vous gériez vous-même la transaction et toutes les ressources. Essayez plutôt d'utiliser RepositoryItemWriter (ou celui qui convient). Vous devrez peut-être fournir un EntityManager et vous assurer que l'écriture est appelée à partir d'une transaction (par exemple, certains @Transactional méthode).

5
JudgingNotJudging