Я следовал за предложением Luca использовать PropertyExtractingDelegatingItemWriter
в качестве автора, и я смог работать с двумя разными объектами за один шаг.
Прежде всего то, что я сделал, чтобы определить DTO, который хранит два объекта/результаты от процессора
public class DatabaseEntry {
private AccessLogEntry accessLogEntry;
private BlockedIp blockedIp;
public AccessLogEntry getAccessLogEntry() {
return accessLogEntry;
}
public void setAccessLogEntry(AccessLogEntry accessLogEntry) {
this.accessLogEntry = accessLogEntry;
}
public BlockedIp getBlockedIp() {
return blockedIp;
}
public void setBlockedIp(BlockedIp blockedIp) {
this.blockedIp = blockedIp;
}
}
Тогда я прошел этот DTO к писателю, а PropertyExtractingDelegatingItemWriter
класса, где я определяю два настроенных методы записать объекты в базу данных, см мой писатель код ниже:
@Configuration
public class LogWriter extends LogAbstract {
@Autowired
private DataSource dataSource;
@Bean()
public PropertyExtractingDelegatingItemWriter<DatabaseEntry> itemWriterAccessLogEntry() {
PropertyExtractingDelegatingItemWriter<DatabaseEntry> propertyExtractingDelegatingItemWriter = new PropertyExtractingDelegatingItemWriter<DatabaseEntry>();
propertyExtractingDelegatingItemWriter.setFieldsUsedAsTargetMethodArguments(new String[]{"accessLogEntry", "blockedIp"});
propertyExtractingDelegatingItemWriter.setTargetObject(this);
propertyExtractingDelegatingItemWriter.setTargetMethod("saveTransaction");
return propertyExtractingDelegatingItemWriter;
}
public void saveTransaction(AccessLogEntry accessLogEntry, BlockedIp blockedIp) throws SQLException {
writeAccessLogTable(accessLogEntry);
if (blockedIp != null) {
writeBlockedIp(blockedIp);
}
}
private void writeBlockedIp(BlockedIp entry) throws SQLException {
PreparedStatement statement = dataSource.getConnection().prepareStatement("INSERT INTO blocked_ips (ip,threshold,startDate,endDate,comment) VALUES (?,?,?,?,?)");
statement.setString(1, entry.getIp());
statement.setInt(2, threshold);
statement.setTimestamp(3, Timestamp.valueOf(startDate));
statement.setTimestamp(4, Timestamp.valueOf(endDate));
statement.setString(5, entry.getComment());
statement.execute();
}
private void writeAccessLogTable(AccessLogEntry entry) throws SQLException {
PreparedStatement statement = dataSource.getConnection().prepareStatement("INSERT INTO log_entries (date,ip,request,status,userAgent) VALUES (?,?,?,?,?)");
statement.setTimestamp(1, Timestamp.valueOf(entry.getDate()));
statement.setString(2, entry.getIp());
statement.setString(3, entry.getRequest());
statement.setString(4, entry.getStatus());
statement.setString(5, entry.getUserAgent());
statement.execute();
}
}
при таком подходе вы можете получить хотел щёток поведение от одного читателя для обработки нескольких объектов и сохранять их в один шаг.
Смешивание процессора и писателя - плохая идея: эти компоненты создали отдельно, чтобы сделать процесс и написать две отдельные проблемы –
Я согласен с вами в общей концепции. Однако, как вы, конечно же, читали исходный вопрос, проблема заключалась в том, чтобы читать элементы один раз и обрабатывать/записывать их двумя совершенно разными способами. Итак, можете ли вы поделиться тем, как решить конкретную проблему, о которой идет речь? – danidemi
Проверьте мой ответ. Обработка выполняется с использованием составного процессора, принимающего один элемент в качестве входных данных, и пользовательский компонент (CompositeResultBean), содержащий результат многократной обработки. Запись с использованием делегирования: CompositeResultBean - это вход и вызов правильного делегированного автора для CompositeResultBean.result1 и CompositeResultBean.result2. Прочитайте один раз, обработайте/напишите с помощью отдельного ItemProcessor/ItemWriter, используя состав и делегирование. Все, что сделано без концепций смешивания –