Интеграция Spring boot с spring batch и jpa
я интегрирую проект spring boot с проектом spring batch и data jpa . Все, что связано с заданием и конфигурацией данных, правильно, за исключением того, что мой результат записи заданий сохраняется в базе данных . после того , как я прочитал файл и обработал его, я не могу записать его в базу данных mysql . Нет ошибки, но нет вставки тоже . интересно, что мой источник данных настроен . потому что перед вставкой я могу получить образец записи из базы данных .пожалуйста, помогите мне решить эту проблема.
Мои приложения.свойства :
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 . он извлекает объект person с id 1 из базы данных, но следующая строка не вставляется в базу данных без ошибок. просто выполняем линию и продолжаем цикл.
2 ответов
решение этой проблемы может быть ближе, чем ожидалось. Вы просто пытались изменить имя компонента transactionManager? С другим именем он не будет использоваться по умолчанию Spring Data JPA.
я воспроизвел вашу проблему, а затем я просто переключился с этого:
@Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
для этого:
@Bean
public ResourcelessTransactionManager resourcelessTransactionManager() {
return new ResourcelessTransactionManager();
}
и, на мой взгляд, это решило проблему. Помните, что "transactionManager" - это имя компонента по умолчанию для transactionManager в Spring Data JPA (по крайней мере, насколько я понимаю, Spring Boot автоматически настраивает его, если он не находит боб с этим именем, и если это так, он использует найденный-и ваши транзакции базы данных проходят через без ресурсов).
вы также можете пропустить этот:
@Bean
public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception {
return new MapJobRepositoryFactoryBean(transactionManager).getObject();
}
и вызовите bean напрямую (просто чтобы быть "более уверенным", что правильный менеджер транзакций используется с пакетом):
@Bean
public JobRepository jobRepository() throws Exception {
return new MapJobRepositoryFactoryBean(resourcelessTransactionManager()).getObject();
}
Дайте мне знать, когда вы тестируете его, и я надеюсь, что это была основная проблема :)
возможно, я пропустил его, но я не вижу, где вы указываете, какой метод доступа к БД вы используете (JPA, Hibernate, JDBC и т. д.). Я предполагаю JPA, но я думаю, что ваш ItemWriter должен расширить один из DB-aware ItemWriters (RepositoryItemWriter,JpaItemWriter,JdbcBatchItemWriter, HibernateItemWriter). Базовый ItemWriter ожидает, что вы будете управлять транзакцией и всеми ресурсами самостоятельно. Попробуйте использовать RepositoryItemWriter (или что угодно вместо этого уместно). Возможно, вам придется предоставить EntityManager и убедиться, что write вызывается из транзакции (например, some @Transactional
метод).