Решил я проанализировать источники трафика на моём сайте и обнаружил, что на сайт частенько заходят в поисках информации о SimpleJdbcInsert
, о чём я толком не рассказывал. Поэтому этой статьёй я постараюсь закрыть этот пробел.
SimpleJdbcInsert
— один из вспомогательных инструментов, предоставляемых Spring Framework JDBC для работы с реляционными базами данных, задача которого — предоставить удобный механизм для вставки новых строк в таблицы.
Структура классов
Прежде всего предлагаю посмотреть на структуру классов, реализуемых SimpleJdbcInsert
:
SimpleJdbcInsert
реализует интерфейс SimpleJdbcInsertOperations
и расширяет класс AbstractJdbcInsert
, который и содержит всю основную логику вставки новых строк в таблицы. По сути SimpleJdbcInsert
реализует классический шаблон проектирования «Адаптер», адаптируя поведение AbstractJdbcInsert
к интерфейсу SimpleJdbcInsertOperations
.
Создание и настройка
SimpleJdbcInsert
и AbstractJdbcInsert
предоставляют два конструктора, которые принимают в качестве единственного аргумента либо экземпляр класса JdbcTemplate
, либо — DataSource
. Поскольку для фактического выполнения insert-запроса используется экземпляр класса JdbcTemplate
, а он обычно доступен в контексте приложения, основанного на Spring Boot, я рекомендую выбирать соответствующий конструктор. В противном случае будет создан новый экземпляр JdbcTemplate на основе переданного экземпляра DataSource
.
SimpleJdbcInsertOperations
объявляет следующие методы для конфигурирования:
withTableName
— для указания названия таблицы, в которую будут выполняться вставки новых строкwithSchemaName
— для указания названия схемы базы данныхwithCatalogName
— для указания названия каталога базы данныхusingColumns
— для перечисления названий колонок, в которые будут вставляться новые данныеusingGeneratedKeyColumns
— для указания названий колонок, значения которых будут сгенерированы на стороне базы данных и должны будут возвращеныwithoutTableColumnMetaDataAccess
— для отключения доступа Spring JDBC к метаданным колонок. Рекомендую делать это только в крайних случаях, так как доступ к метаданным колонок может указать на наличие ошибок заранее при компиляции экземпляра SimpleJdbcInsert.includeSynonymsForTableColumnMetaData
— для использования синонимов (специфично для Oracle)
Все методы настройки по своей сути являются обёртками вокруг методов set…
класса AbstractJdbcInsert для возможности объединения их вызовов в цепочки.
Примеры создания и настройки экземпляров SimpleJdbcInsert
Для примеров ниже будет использоваться следующая схема БД PostgreSQL:
Пример создания экземпляра SimpleJdbcInsert
для вставки новых строк с колонками c_title
и c_details
в таблицу t_todo
схемы sandbox
с возвратом сгенерированного значения из колонок id
и c_created_at
:
Альтернативный вариант создания, когда SimpleJdbcInsert
расширяется собственным классом:
Ещё один вариант, когда расширяется AbstractJdbcInsert
:
Созданные экземпляры класса SimpleJdbcInsert
и классов-наследников AbstractJdbcInsert
являются потоко-безопасными, поэтому для каждой таблицы можно создать один экземпляр соответствующего класса и использовать его для всех случаев.
Использование
SimpleJdbcInsert
и AbstractJdbcInsert
для вставки строк предоставляют по два варианта каждого метода, разница заключается в типе аргумента, в котором передаются подставляемые в запрос данные: Map<String, Object>
или SqlParameterSource
.
execute
Метод execute
возвращает в ответ количество затронутых запросом строк, которое в большинстве случаев должно равняться единице.
executeAndReturnKey
Метод executeAndReturnKey
возвращает в ответ сгенерированное на стороне базы данных значение колонки, название которой было указано в usingGeneratedKeyColumns
или setGeneratedKeyNames
, однако работать этот метод будет только в том случае, если такая колонка была указана одна, а её тип данных можно выразить в виде java.lang.Number
. Типичное применение этого метода — вставка новой строки с получением сгенерированного идентификатора строки.
executeAndReturnKeyHolder
Метод executeAndReturnKeyHolder
возвращает в ответ экземпляр KeyHolder
, при помощи которого можно получить доступ к сгенерированным на стороне базы данных значениям колонок. Это может быть полезно, когда в таблице присутствует несколько колонок, значение которых должно быть сгенерировано при вставке новой строки. В моём примере есть две такие колонки: id
— идентификатор строки и c_created_at
— метка времени создания записи.
executeBatch
executeBatch
— метод для пакетной вставки новых строк в таблицу, возвращающий массив количества вставленных строк для каждой вставки. По сути это аналог execute
для пакетной вставки.
Рекомендации
- Создавайте экземпляры класса
SimpleJdbcInsert
и классов-наследниковAbstractJdbcInsert
с использованием конструктора, принимающего в качестве аргумента экземпляр классаJdbcTemplate
- Для
AbstractJdbcInsert
применяйте шаблон проектирования «Адаптер класса» - Для
SimpleJdbcInsert
применяйте шаблон проектирования «Адаптер объекта» - Вызывайте метод
compile
для «компиляции» объекта, этим вы гарантируете, что в промежутке между созданием экземпляра класса и его первым использованием не произойдёт никаких изменений.
Демонстрация примеров и полезные ссылки
Для демонстрации описанных в статье примеров я создал проект, в котором можно проверить работу SimpleJdbcInsert
на примере баз данных H2 (встроенная) и PostgreSQL (Docker, запуск с профилем pgindocker).