#java #spring #jdbc #spring-batch
Вопрос:
В моем проекте мне нужно выполнить запрос внутри пакетного процессора Spring, чтобы проверить какое-либо поле.
Как я могу это сделать?
ИЗМЕНИТЬ: Добавление источников:
Это определение шага:
@Bean
public Step step1(JdbcBatchItemWriter<CaricoDTO> step1Writer) {
return stepBuilderFactory.get("step1").<CaricoDTO, CaricoDTO>chunk(10).reader(multiResourceItemReader())
.processor(processorStep1()).writer(step1Writer).build();
}
Это определение multiResourceItemReader
:
@Bean
public MultiResourceItemReader<CaricoDTO> multiResourceItemReader() {
MultiResourceItemReader<CaricoDTO> resourceItemReader = new MultiResourceItemReader<CaricoDTO>();
ArrayList<Integer> indexesToRemove = new ArrayList<Integer>();
Resource[] inputResources = null;
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
try {
inputResources = patternResolver.getResources(inputPath);
} catch (IOException e) {
e.printStackTrace();
}
resourceItemReader.setResources(inputResources);
resourceItemReader.setDelegate(step1Reader());
resourceItemReader.setComparator(new FileComparator());
return resourceItemReader;
}
Это step1Reader
:
@Bean
public FlatFileItemReader<CaricoDTO> step1Reader() {
FlatFileItemReader<CaricoDTO> reader = new FlatFileItemReader<CaricoDTO>();
reader.setLinesToSkip(1);
reader.setLineMapper(new DefaultLineMapper<CaricoDTO>() {
{
setLineTokenizer(new DelimitedLineTokenizer("|") {
{
setNames(new String[] { ..... });
}
});
setFieldSetMapper(new BeanWrapperFieldSetMapper<CaricoDTO>() {
{
setTargetType(CaricoDTO.class);
}
});
}
});
return reader;
}
Это мой процессор.:
@Bean
public CaricoDTOItemProcessorStep1 processorStep1() {
CaricoDTOItemProcessorStep1 processorStep1 = new CaricoDTOItemProcessorStep1();
return processorStep1;
}
Это мое определение процессора:
public class CaricoDTOItemProcessorStep1 implements ItemProcessor<CaricoDTO, CaricoDTO> {
private String fileName;
private static final Logger log = LoggerFactory.getLogger(CaricoDTOItemProcessorStep1.class);
@Override
public CaricoDTO process(CaricoDTO carico) throws Exception {
carico.setDataCaricamento(new Date(System.currentTimeMillis()));
carico.setFileName(carico.getResource().getFilename());
return carico;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
А это мой писатель:
@Bean
public JdbcBatchItemWriter<CaricoDTO> step1Writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<CaricoDTO>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql(....)
.dataSource(dataSource).build();
}
Комментарии:
1. Что вы сделали до сих пор? Как выглядит ваш проект / настройка компонентов? Простым и понятным способом было бы использовать
JdbcTemplate
, но могут быть и другие / лучшие способы сделать это.2. @tmarwen У меня есть считыватель, считывающий из csv-файла, процессор и писатель, записывающий в бд, но мне приходится отбрасывать некоторые записи из-за значений, отсутствующих в таблицах домена. Я использую h2 в качестве сохранения данных
3.Я все еще не понимаю общей картины. Не могли бы вы добавить минимальный воспроизводимый код из своей базы кода? Как вы уже выполняете чтение / запись, используете пакет Spring
ItemReader
/ItemWriter
?4. @tmarwen Я добавил информацию к своему вопросу.
Ответ №1:
Учитывая небольшие детали в основной операции, я предполагаю, что общее решение будет принято.
Учитывая классическую настройку пакетного проекта Spring, у вас должен быть доступ к org.springframework.jdbc.core.JdbcTemplate
компоненту, подключенному к цели javax.sql.DataSource
, который вы можете просто ввести в один из компонентов вашего пакетного сотрудника:
org.springframework.batch.item.ItemReader
org.springframework.batch.item.ItemWriter
org.springframework.batch.item.ItemProcessor
Предполагая, что вам нужно выполнить некоторую проверку, прежде чем приступить к обработке элемента (и, возможно, отказаться от него), вы можете ввести JdbcTemplate
компонент, выполнить запрос для проверки инвариантов модели, а затем выполнить соответствующие действия:
public class CaricoDTOItemProcessorStep1 implements ItemProcessor<CaricoDTO, CaricoDTO> {
@Autowired
private JdbcTemplate jdbcTemplate;
private String fileName;
private static final Logger log = LoggerFactory.getLogger(CaricoDTOItemProcessorStep1.class);
@Override
public CaricoDTO process(CaricoDTO item) throws Exception {
boolean someValue = jdbcTemplate.queryForObject("SELECT some_field FROM some_table WHERE some_other_field = 0", (rs, rowNum) -> rs.getBoolean(0));
if (someValue) {
carico.setDataCaricamento(new Date(System.currentTimeMillis()));
carico.setFileName(carico.getResource().getFilename());
return carico;
} else {
return null; // causes the item to be discarded from processing
}
}
}
Излишне говорить, что ваш запрос будет зависеть от варианта использования вашего домена и нуждается в обновлении.
Комментарии:
1. Большое спасибо. Я проверю ваше решение.
2. Спасибо. Это решило мою проблему!