Статьи Утилиты Telegram YouTube VK Видео RuTube Отзывы

Добавление записи через POST-запрос в Spring Boot

Исходники

8 марта 2026

Тэги: Java, json, maven, rest, Spring Boot, SQL, руководство.

Содержание

  1. Репозиторий
  2. Сервисный слой
  3. Контроллер и валидация входных параметров

В статье Добавление записи через POST-запрос в Spring Boot мы узнали как читать данные из БД. Но чтение данных - это лишь малая часть всех операций, которые встречаются в типичном java-приложении. Теперь попробуем добавить rest-метод для создания новых записей.

За основу возьмём наше приложение из указанной статьи. Оно состоит из трёх слоёв: работа с БД (repository), бизнес-логика приложения (service) и сам rest-интерфейс (controller), который обрабатывает входящий json и генерирует исходящий.

Репозиторий

Начнём с доработки ProfileRepository, где до сих пор был только один метод чтения данных. Добавляем ещё один sql-запрос в виде константы в начале класса:

@Repository
@RequiredArgsConstructor
public class ProfileRepository {
    // SQL_GET_PROFILE_BY_ID

    private static final String SQL_INSERT_PROFILE =
            "insert into profile (first_name, last_name, age) values (:firstName, :lastName, :age)";
    // ...
}

При добавлении новой записи нам достаточно всего три поля. id будет сгенерирован в БД автоматически, т.к. он имеет тип serial.

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

Вот реализация метода insertProfile() для добавления новой записи в БД:

public void insertProfile(String firstName, String lastName, int age) {
    jdbcClient.sql(SQL_INSERT_PROFILE)
            .param("firstName", firstName)
            .param("lastName", lastName)
            .param("age", age)
            .update();
}

Всё предельно просто: сначала с помощью jdbcClient указываем текст sql-запроса, затем передаём все параметры, которые используются в этом запроса и в конце вызываем метод update(). Этот метод используется для любых модификаций данных (в отличие от query(), который нужен для чтения).

Сервисный слой

Перейдём к сервисному слою. Интерфейс ProfileService не отличается оригинальностью:

void createProfile(String firstName, String secondName, int age);

Его реализация в ProfileServiceImpl. Здесь по сути только логируем параметры и вызываем метод репозитория:

@Override
public void createProfile(String firstName, String secondName, int age) {
    log.info("Create profile with firstName={}, secondName={}, age={}", firstName, secondName, age);
    profileRepository.insertProfile(firstName, secondName, age);
}

Контроллер и валидация входных параметров

Согласно архитектуре restful-сервисов, чтение данных мы делаем при помощи GET-запросов, а создание - при помощи POST. Также хотелось бы отметить, что у GET-запроса не может быть тела запроса (body), все его параметры перечисляются в строке запроса. А POST-запрос может иметь тело, в которое мы будем помещать целевой json.

Сперва нам нужно добавить в проект ещё одну зависимость spring-boot-starter-validation, которая позволяет валидировать входящие запросы:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Перейдём к нашему контроллеру ProfileController и добавим в него метод создания профиля.

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void createProfile(@Valid @RequestBody ProfileRequest request) {
    profileService.createProfile(
            request.firstName(),
            request.lastName(),
            request.age()
    );
}

В качестве аргумента метод принимает объект ProfileRequest, реализованный как record-class:

public record ProfileRequest(
        @NotNull
        String firstName,
        @NotNull
        String lastName,
        @NotNull
        @Min(1)
        Integer age
) {
}

Эта модель представляет собой ровно тот объект, который мы ожидаем в теле запроса. Имена полей в json должны совпадать с именами полей в классе (при желании это можно переопределить дополнительной аннотацией). Дополнительно накладываем ограничения из пакета jakarta.validation.constraints на каждое поле.

Аннотация @NotNull применима для ссылочных типов и означает обязательность этого поля в запросе. Обратите внимание, что тут мы специально используем ссылочный Integer, который допускает null, а не примитивный int, который по умолчанию равен нулю. Ссылочный числовой тип вместе с @NotNull позволяет проверять обязательность числовых типов.

Аннотация @Min говорит сама за себя и ограничивает числовые типы минимально возможным значением. Тем самым мы никогда не допустим, чтобы нам передали отрицательное число в качестве возраста.

Чтобы эти проверки работали для входящего json, параметр метода надо снабдить аннотацией @Valid, а чтобы именно в этот класс был преобразован входящий json, также добавляем @RequestBody. Внутри просто вызываем сервисный слой.

Аннотация @PostMapping указывает на то, что это обработчик POST-запроса. В скобках можно указать относительный урл, но в данном случае мы его не указали, поэтому запрос надо будет кидать по тому адресу, который указан на уровне контроллера, то есть /profiles. @ResponseStatus показывает, какой http-код нужно вернуть в ответ. В данном случае мы опять следуем rest-соглашениям и возвращаем код 201 - «Created».

Теперь мы готовы к тому, чтобы выполнить rest-запрос на создание новой записи в БД. Запускаем приложение и отравляем указанный POST-запрос по адресу http://127.0.0.1:8080/profiles. В http-заголовках обязательно указываем Content-Type: application/json.

{
  "firstName": "Петр",
  "lastName": "Сидоров",
  "age": 14
}

В ответ в случае успеха получаем http-статус 201. Если же мы попытаемся нарушить наши ограничения по полям, то получим json с подробным описанием ошибки.

Таким образом, Spring Boot позволяет буквально за 5 минут создать полноценный обработчик POST-запроса с валидацией входящих параметров.

В следующей статье Обновление записи через PUT-запрос в Spring Boot рассмотрим как можно обновлять записи.


См. также

Облако тэгов

Kotlin, Java, Spring, Spring Boot, Spring Data, Spring AI, SQL, PostgreSQL, Oracle, H2, Linux, Hibernate, Collections, Stream API, многопоточность, чат-боты, нейросети, файлы, devops, Docker, Nginx, Apache, maven, gradle, JUnit, YouTube, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.

Последние статьи


Комментарии

29.10.2022 16:50 Антон

Подскажите, а как получить id сохраненного профиля, если мы возвращаем только статус CREATED?

29.10.2022 21:35 devmark

Касательно данного примера, полученный id можно посмотреть в БД после вставки. Если говорить о том, как получить этот id программно, то нужно в метод jdbcTemplate.update() передать дополнительный параметр. Этот параметр имеет тип GeneratedKeyHolder и после выполнения запроса в нём будет содержаться сгенерированный id. Также нужно в конце sql-запроса с insert дописать " returning id".

Добавить комментарий

×

devmark.ru