Spring Batch: эффективный способ запроса результатов хранимой процедуры в тасклете - PullRequest
0 голосов
/ 04 марта 2020

Моя цель - запросить результаты хранимой процедуры (sql сервер) с помощью настраиваемого сопоставителя строк в тасклете Spring Batch.

Я использую Spring Boot (версия 2.2.2.RELEASE) и Spring Batch (4.2.1.RELEASE).

Пример:

Хранимая процедура:

CREATE PROCEDURE storedProcName @numbers VARCHAR(max), @day DATE
AS
SET NOCOUNT ON;

SELECT something, something2, something3
FROM sometable
WHERE ids in (select value from string_split(@numbers,','))
AND day = @day

Пользовательский сопоставитель строк:

public class CustomRowMapper implements RowMapper<CustomObject> {
    private static final String SOMETHING = "something";
    private static final String SOMETHING2 = "something2";
    private static final String SOMETHING3 = "something3";

    @Override
    public CustomObject mapRow(ResultSet resultSet, int i) throws SQLException {
        CustomObject customObject = new CustomObject();
        customObject.setSomething(resultSet.getString(SOMETHING));
        customObject.setSomething2(resultSet.getString(SOMETHING2));
        customObject.setSomething3(resultSet.getInt(SOMETHING3));

        return customObject;
    }
}

Выполните хранимую процедуру и запросите результаты:

SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
        .withProcedureName("storedProcName")
        .returningResultSet("test", new CustomRowMapper());
Map<String, Object> out = jdbcCall.execute(parameterSource);
List<CustomObject> customObjects = (List<CustomObject>) out.get("test");

Это работает нормально, но должен быть более эффективный способ сделать это? Но я не нашел ничего полезного.

1 Ответ

2 голосов
/ 05 марта 2020

должен быть более эффективный способ сделать это

Spring Batch предоставляет StoredProcedureItemReader, который может вызвать данную хранимую процедуру и выполнить итерацию по ее Результаты. Это также позволяет вам использовать пользовательский преобразователь в качестве того, который вы определили.

В соответствии с вашим фрагментом кода вы вызываете процедуру и получаете List<CustomObject>, по которому вам нужно будет выполнить итерацию в какой-то момент. Поэтому я думаю, что ориентированный на куски тасклет с StoredProcedureItemReader<CustomObject> является хорошим выбором для вас:

@Bean
public StoredProcedureItemReader<CustomObject> itemReader() {
    return new StoredProcedureItemReaderBuilder<CustomObject>()
            .procedureName("storedProcName")
            .rowMapper(new CustomRowMapper())
            // set other properties
            .build();
}

Редактировать: показать, как вернуть синхронизированный читатель

@Bean
@StepScope
public SynchronizedItemStreamReader<CustomObject> itemReader() {
    StoredProcedureItemReader<CustomObject> reader = new StoredProcedureItemReaderBuilder<>()
            .procedureName("storedProcName")
            .rowMapper(new CustomRowMapper())
            // set other properties
            .build();

    SynchronizedItemStreamReader<CustomObject> synchronizedReader = new SynchronizedItemStreamReader<>();
    synchronizedReader.setDelegate(reader);
    return synchronizedReader;
}
...