Spring JDBC Template Example

В прошлой статье мы говорили о подключении Java-приложения к базе данных посредством JDBC. Сегодня поговорим о так называемом JDBC Template — это некое API, входящее в состав Spring Framework и обеспечивающее более удобное взаимодействие с базой данных с меньшим количеством бойлер-плейта (обслуживающего кода).

Итак, создаем новый SpringBoot проект. Как это сделать мы говорили в предыдущей статье.

Допустим, Вы уже создали проект и он абсолютно чистый и смотрит сейчас на Вас с экрана Вашего монитора.

Открываем файл application.properties в папке resources и добавляем туда следущий код:

Базу данных и таблицу предлагаю ту же, которую мы использовали в этой статье. Либо Вы можете использовать любую свою.

В классе SpringBootHelloWorldApplication :

… добавляем «конфиг» нашего источника данных:

Здесь мы конфигурируем источник данных как бин и указываем каким именно префиксом в application.properties прописан конфиг подключения к БД. Так же указываем, что это первичный источник данных.

Открываем pom.xml и добавляем зависимости для PostgreSQL и spring-boot-starter-jdbc. Вот полный листинг pom.xml:

Теперь нам надо решить, что именно мы будем делать и как это тестировать. Предлагаю научиться делать select-запросы и добавлять данные. У нас есть три варианта для того, чтобы сделать для Вас результат очевидным:

  • REST-запросы.
  • WEB-представление
  • Unit-тесты.

Я решил, что быстрее и правильнее будет сделать так называемый контроллер и тестировать наше приложение через него. Большинство разработчиков используют для этой цели cUrl или Postman. Про это на моем блоге будут отдельные статьи. С налету так просто оседлать Постмен не получится, поэтому будем использовать то, что есть. Ну, а чтобы облегчить жизнь изучающим, следующие три статьи я сделаю в поддержку этой:

  • в первой мы попробуем «подергать» эти же самые контроллеры «курлом» (cUrl);
  • во второй — напишем юнитесты.
  • в третьей — сделаем отображение информации в web-виде на обычной html-страничке.

Выбираем в верхнем меню Tools -> Http Client -> Test RESTful Web Service, у вас должна открыться вот такая панелька и если у Вас последняя версия Intelij Idea, то в верхней ее части будет пункт Convert request to the new format:

Жмем его, увидим следующее:

Меняем запрос на следующее:

GET http://localhost:8080/api/all

И добавляем новый класс JdbcController. Вот его код:

Теперь немного теории:

Далее — рассказываю своими словами, достаточно косноязычно и на пальцах. Основа этого Вашего Интернета — запрос. Когда вы вводите какой-то URL, например www.yandex.ru, браузер делает запрос к серверу Яндекса с просьбой вернуть ему какой-то контент. В данном случае HTML-страницу. Как правило, это запрос GET. Как его пощупать?

Открываем Ваш браузер (большинство сейчас пользуется Хромом), жмем F12, переходим на вкладку Network, идем по адресу www.yandex.ru, видим что-то похожее на:

Главное я выделил желтым. Итак, пре переходе по адресу, браузер дернул GET-запросом URL https://yandex.ru, сервер вернул код 200. Запросы могут быть не только GET, но так же и POST, PUT и так далее. В POST запросах как правило в теле запроса передают какие-то данные. Кода ответа так же могут быть разные. Сейчас не будем останавливаться на этом. Для нас важно то, что «дергая» тот или иной запрос, мы можем получать не только HTML-страницу в ответ, но и какую-то информацию в разных форматах. Это может быть и бинарный файл и JSON и XML и сырые текстовые данные.

В Java-терминологии как бы принято, что контроллерэто класс содержащие обработчики тех или иных запросов.

Есть так же сервис, компонент и репозиторий. В любом случае — все это для спринга Бины (Beans) с возможностью автовайринга.

Про контроллер я сказал выше, про остальные:

Сервис набор сервисных методов. Принято, что контроллер логику обработки внутри себя не содержит, а вызывает соответствующий сервисный метод. То есть сервис — это основная обрабатывающая бизнес-логика, набор сервисных методов.

Репозиторий — набор ORM-методов для работы с БД.

Компонент сейчас используется все реже и реже. Это примерно то же, что и сервис, только не про основную сервисную логику, а про все то, что не вместилось в это понятие в рамках деления ответственности внутри вашего проекта.

Контроллеры тоже бывают 2-х видов: @Controller и @RestController. Первый используется для классов, обслуживающих mvc функционал. Короче, в случаях, когда у вас есть, например, какая-то jsp-страничка и вам надо выплюнуть на нее какой-то результат запроса.

@RestController используется для любых REST-запросов. Если посмотреть довольно навороченное описание на Википедии, то самым простым объяснением, что это такое является: «REST-запросы — способ вызов удаленных процедур и методов посредством HTTP-запросов«.

Теперь разберем наш первый RestController по деталям (класс JdbcController):

Аннотация @RestController говорит нам о том, что это именно контроллер, обслуживающий REST-запросы.

Аннотация @RequestMapping(«/api») задает базу URL для запросов. То есть доступ к этим методам возможен по URL, содержащему /api в составе пути. То есть, другими словами:

  • Запрос №1 будет доступен по пути localhost:8080/api/request1
  • Запрос №2 будет доступен по пути localhost:8080/api/request2
  • И так далее…

Аннотация @GetMapping(«/all») — указывает путь до конкретного ендпоинта. Методы, вызываемые по этим URL еще называют ендпоинтами (endpoint).

public String gelAllUsers() — сигнатура метода. Мы говорим, что в ответ http-клиенту мы вернем строку. Это еще называют — «вернем в респонсе (response)«.

Ну и в коде мы возвращаем просто строку — «1«.

Теперь, возвращаясь назад, запускаем наше приложение (щелкаем правой кнопкой мыши на SpringBootHelloWorldApplication в дереве проекта и там выбираем Run..) и видим в консоли примерно следующее:

Строчки …

Tomcat started on port(s): 8080 (http) with context path ''
Started SpringBootHelloWorldApplication in 1.903 seconds (JVM running

… как правило означают, что приложение успешно запущено на 8080 порту. Это стандартный порт для SpringBoot-приложений по умолчанию. Соответственно обращаться к этому приложению вы будете по адресу http://localhost:8080/.

Теперь переходим на вкладку с нашим запросом rest-api.http И запускаем его:


Самое главное: «что нажимать» и «важный нам результат» я выделил желтым: запрос нам ответил, собственно то, что мы указали в методе нашего JdbcController’а по имени getAllUsers() — return «1»;

Еще раз повторю, что если у Вас нет IntelijIdea и Постмана — оставайтесь со мной, в следующих статьях я расскажу как сделать все это без Идеи или если у Вас старая IntiljIdea и там нет вкладки http-клиента.

Идем дальше: теперь нам надо обратится к БД, запросить данные и вывести их при обращению к ендпоинту.

Распространенной практикой в интернете является создание папки service, куда помещаются все сервисы, так же поступают с контроллерами и с классами, описывающие конкретные таблицы. Причем для сервисов создается интерфейс Service и к нему пишется реализация ServiceImp. Большинство начинающих копируют это в лоб, не понимая зачем так вообще делать. А потом они приходят на проекты, где главенствует DDD и «обтекают», ибо «затанцевали» уже все эти ServiceImpl. Интерфейсы часто используют в тех случаях, когда у Вас несколько реализаций метода, объявленного в интерфейсе для разных кейсов и используется, например, шаблон Фабрика. А если у нас пара сервисных методов обращения к БД, мы можем написать обычное DAO в одном классе и не замораивать себе голову. Так и сделаем. Начнем с простого метода, возвращающего количество записей. Создаем класс DaoService. Вот его листинг:

Немного комментариев:

Мы используем аннотацияю @Service, чтобы потом использовать @Autowire для организации слабосвязнного кода и использования этого сервиса в контроллере.

Взгляните на самое вкусное — метод getCount(), возвращающий количество записей! Никакого бойлерплейта, все лаконично. Одна строчка всего! Собственно, надеюсь, помощи с SQL Вам не потребуется.

Ну а следующие строчки — это конструктор, в который передается сконфигурированный ранее Datasource.

Контроллер поменялся теперь так:

Надо, правда, сказать, что выдача в response интА (int) это, конечно, лютый кошмар. Так не делается! Здесь это исключительно для понимания процесса и визуализации наших действий.

Теперь нужно реализовать выдачу из таблицы данных в контроллере. Для этого нам понадобится так называемый Mapper. Приступим!

Добавляем в наше DaoService новый метод:

Так же немного меняем контроллер:

И добавляем класс нашего пользователя, уже знакомый нам по предыдущим статьям (но у него теперь появится еще один новый конструктор):

Мы добавили второй метод и поменяли ендпоинты. Сейчас этот метод будет возвращать в консоль []. Да, не забудьте добавить второй метод нашему тестовому клиенту:

Нам осталось реализовать вставку и все.

Добавляем новый метод в контроллер:

Реализуем метод addNew в DaoService:

Перезапускаем приложением и добавляем новый тестовый ендпоинт:

Как видим, метод успешно отработал и выдал нам список пользователей, состоящий из одного, только что добавленного.

Вот такая запись в параметрах метода @RequestParam(«name») String name, … как раз позволяет указывать «переменную-пути», в которой вы, как я показал на скриншоте, можете передавать различные значения.

Конечно же в нормальных приложениях так не делают. Во-первых, для добавления новых записей используют Post, во-вторых, данные для добавления передают в теле запроса, как правило в JSON-виде. Но у нас и так получилось много писанины, поэтому я написал как можно более сокращенное и простое решение.

Так же часто вывод списка пользователей в резульате исполнения метода добавляют в сам сервисный метод, а не в контроллер.

Нам этом пока все. Напомню, скоро напишу как все это сделать без IntelijIdea и Postman, напишем так же уни-тест для всего это хозяйства. Удачи!

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *