Spring Framework и работа с базами данных: JdbcTemplate

Для работы с реляционными базами данных в Spring Framework предусмотрен такой замечательный инструмент как JdbcTemplate, который является обвязкой вокруг стандартных средств JDBC. JdbcTemplate прост и гибок в применении, его возможностей вполне достаточно для реализации проектов малых и средних размеров. В JDBCTemplate не предусмотрены стандартные средства ORM в отличии от Hibernate или JPA, так что при его использовании нужно самостоятельно писать мапперы, которые будут преобразовывать данные полученные из БД в объекты классов сущностей.

Настройка проекта

Создадим новый Maven-проект и добавим в зависимости spring-jdbc и spring-context. Кстати, spring-context в нашем случае нужен только потому что я буду демонстрировать работу Spring JDBC в рамках Spring-приложения. Так же Spring JDBC можно использовать вне контекста Spring и даже в проекте не использующем Spring. Так же для тестов нам понадобятся junit и h2. При разработке приложения без Spring Boot список зависимостей будет следующий:

spring-boot-starter-logging я добавил, чтобы не отвлекаться на настройку логгирования. Альтернативный набор зависимостей, если мы разрабатываем приложение с использованием Spring Boot, будет следующим:

Архитектура приложения, используемого в данном примере, подразумевает наличие класса-сущности и DAO-класса, который будет реализовывать работу с базой данных.

Исходные данные

В корневой директории ресурсов создадим файл schema.sql, из которого Spring JDBC будет создавать структуру базы данных перед тестированием:

Так же рядом добавим файл data.sql, из которого будет заполняться база:

Теперь опишем класс-сущность Person:

И наконец опишем DAO-интерфейс и класс, его реализующий:

Если DAO-класс используется не в Spring-приложении, то аннтоацию @Component можно убрать. Так же обратите внимание, что объект класса JdbcTemplate внедряется через конструктор. Это даёт независимость от контекста Spring и возможность сделать свойство класса final.

Тестирование

Подготовим класс тестов:

В наших тестах контекст Spring использоваться не будет, так как в этом нет никакой необходимости.

Напишем тесты:

  • findAll() не должен возвращать null и должен возвращать список всех объектов, находящихся в таблице.
  • findOne(String id) должен возвращать объект с указанным идентификатором, либо null, если объект не существует.
  • save(Person person) должен сохранять объект и возвращать его сохранённую версию, либо выбрасывать исключение DataIntegrityViolationException в случае попытке сохранения объекта с невалидными данными.
  • delete(String id) должен удалять запись с указанным идентификатором и возвращать количество затронутых записей.

Весь класс тестов целиком:

Реализация

Для получения данных из БД у JdbcTemplate есть несколько методов, но для нашего примера достаточно самого простого варианта с использованием метода query. Аргументы этого метода: SQL-запрос, список параметров запроса в виде массива объектов, если таковые есть и маппер, который будет полученные данные превращать в объекты нужного нам класса. Параметры запроса указываются в запросе при помощи вопросительного знака и подставляются по порядку. Вызов

будет приведён к виду

Так же при необходимости можно задавать порядковый номер параметра запроса:

что равноценно

Стоит помнить, что порядковые номера параметров запроса начинаются с 1, а не с 0.

Для добавления, изменения или удаления записей в таблицах БД используются методы update и batchUpdate. В нашем случае достаточно update.

Реализация DAO-интерфейса, удовлятворяющая описанным тестам:

На этом моменте тесты должны проходить успешно и покрывать 100% кода PersonRepository и PersonRepositoryImpl.

Более подробно о JdbcTemplate в официальной документации Spring.