Batch операции в Spring JDBC

wwc8dИспользование batch режима выполнения запросов обычно гораздо эффективнее. В этом режиме запросы не выполняются сразу, каждый по отдельности, а накапливаются и выполняются одним большим запросом с множеством данных. Например, если вы делаете несколько update запросов, то каждый запрос будет выполнен как отдельный самостоятельный запрос. В batch режиме ваши update запросы будут отправлены одним заданием, что производительнее.

В этом примере используется структура данных и код из статьи «запросы в Spring JDBC».

Batch операции над списком объектов.

Самое приятное улучшение, которое вносит в обычные batch запросы, это автоматическое создание batch’а из массива объектов и запроса. Если используется NamedParameterJdbcTemplate, вы можете написать запрос имена параметров которого совпадают с именами полей класса. Затем из массива объектов необходимо получить массив параметров и передать его вместе с запросом в метод batchUpdate(). Всё остальное Spring делает сам.

Ручное задание параметров batch запросов

При всём удобстве, у подхода описанного выше есть пара недостатков: во-первых он работает только с NamedParameterJdbcTemplate, во-вторых требует наличия класса с именно такими полями, как указаны в запросе. Если какое-либо из требований удовлетворить нельзя, приходится использовать другие инструменты. Стандартным решением является реализация callback интерфейса BatchPreparedStatementSetter, который и будет наполнять данными каждый конкретный элемент batch’а.

В BatchPreparedStatementCreator необходимо реализовать два метода. getBatchSize() сообщает Spring JDBC какой размер данных ожидать, setValues() вызывается столько раз, сколько вернул getBatchSize()  и получает в качесте аргументов PreparedStatement и номер текущего элемента batch’а. setValues() должен соответствующим образом выставить параметры PreparedStatement.

Разделение batch’ей.

В некоторых случаях размер данных для одного batch может быть насколько большой, что его было бы удобнее разделить на несколько подбатчей. Это можно сделать вручную, например разбив коллекцию на несколько частей или лучше поручить Spring JDBC. Для использования subbatch необходимо реализовать (да да, ещё один) интефейс ParameterizedPreparedStatementSetter. В отличие от BatchPreparedStatementSetter он типизируется конкретным объектом и самостоятельно не управляет размером batch’а.

Реализация ParameterizedPreparedStatementSetter передаётся методу batchUpdate() вмест с размером реального batch, который будет передан в базу, коллекцией объектов с данными и запросом.

Код примера доступен на github.