5 апреля 2024
Тэги: Collections, GraphQL, json, Kotlin, Spring Boot.
В прошлой статье GraphQL в Spring Boot мы создали приложение на Kotlin с API в формате GraphQL, в котором есть две сущности: Книга и Автор. Также научились расширять стандартный набор типов graphql и решили «проблему N+1» с помощью пакетной подгрузки дочерних сущностей. Исходники проекта доступны на github.
Теперь давайте рассмотрим как можно менять данные с помощью GraphQL.
Для изменения данных в GraphQL используются так называемые «мутации». По сути это обычные методы со входными и выходными параметрами, доступные через протокол взаимодействия GraphQL.
Давайте рассмотрим создание мутации на конкретном примере. Доработаем наше приложение, в котором есть сущности «Книга» и «Автор» таким образом, чтобы можно было создавать новых авторов. Чуть позже мы увидим, что сама логика создания инкапсулируется в обычном методе, поэтому все виды изменения данных (создание, обновление, удаление) делаются привычным образом.
Сначала добавим новый тип в нашу graphql-схему (файл schema.graphqls):
В схеме должен быть объявлен один тип с именем Mutation, внутри которого, по аналогии с типом Query, собраны все методы-мутации. Входные параметры методов, используемые в мутациях, должны быть объявлены с ключевым словом input:
В нашем случае мы создаём новый input под названием AuthorCreationRequest, который содержит все поля из сущности Author, кроме id. Вновь созданная сущность возвращается уже как Author, которую мы определяли ранее:
Этих изменений в схеме достаточно, поэтому перейдём к написанию кода.
Сначала создадим data-класс AuthorCreationRequest один в один как мы определили его в схеме:
Затем доработаем AuthorRepository, который представляет собой слой взаимодействия с хранилищем данных. В реальном проекте тут должно быть взаимодействие с БД, но мы для простоты храним объекты в памяти, т.к. JDBC API выходит за рамки данной статьи.
Добавим в репозиторий метод createAuthor():
Тут мы создаём новый объект типа Author, инициализируя его полями из запроса. Также назначаем id подобно реальной базе данных: ищем максимальный id из уже созданных и увеличиваем его на 1. Наконец, добавляем в мапу AUTHORS новый объект с ключом, равным его id. Обратите внимание, что мапа должна иметь тип MutableMap, т.к. в прошлой статье она была обычной Map, т.е. только для чтения.
В принципе, вы можете реализовать какую угодно логику внутри метода createAuthor(). GraphQL лишь обеспечивает вам его вызов с параметром определённого типа.
Наконец, создадим новый спринговый контроллер MutationController, в котором удобно держать все мутации. Хотя технически мы могли бы использовать уже созданный ранее контроллер с запросами на чтение.
Здесь мы внедряем в контроллер слой взаимодействия с БД. В реальном проекте тут должен быть сервисный слой, но он бы просто проксировал вызов метода, поэтому пропустим его для краткости.
Сам метод createAuthor() помечается аннотацией @MutationMapping. В скобках явно указано имя метода из схемы graphql, но в данном случае это делать не обязательно, т.к. они совпадают. Входной параметр AuthorCreationRequest помечается аннотацией @Argument и в скобках указывается имя этого параметра из схемы.
Теперь запустим проект и перейдём на эндпоинт 127.0.0.1:8080/graphiql, где сможем вызвать мутацию с помощью отладочного веб-интерфейса graphiql.
В отличие от запросов на чтение данных, которые начинаются с ключевого слова query, запросы мутаций начинаются со слова mutation. Далее в фигурных скобках указывается имя метода, ему полностью передаются все input-параметры. А вот в качестве результата работы метода можно запросить не всё подряд, только нужные поля.
Как видите, создание мутаций в graphql даже проще, чем чтение данных, т.к. здесь нет «проблемы N+1». По сути происходит обычное проксирование вызова метода. Поэтому логика изменения данных не будет сильно отличаться от привычного нам restful API.
Kotlin, Java, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.