Build a CRUD API with Spring Boot and GraphQL

Hello everyone, today we will learn how to build CRUD API using Spring Boot, GraphQL, H2DB and Spring Data JPA.

GraphQL is a specification for how to talk with an API. It's typically used over HTTP where the key conception is to POST a "query" to an HTTP endpoint, instead of hitting different HTTP endpoints for different resources. GraphQL is designed for developers of web/mobile apps to be able to make API calls to fetch precisely the data they require from their backend APIs.More Info https://graphql.org/

We have two data models: Author and Book. So each book must belong to an author and an author may have multiple books under it. So Book will have a many-to-one relationship with Author. For book and author, we will perform Create, Read, Update and Delete operations using GraphQL APIs. 

You can download the complete source code from our GitHub repository.

CRUD GraphQL APIs:

Create Author:


Create Book:


Update Author:


Update Book:


Read all Books:


Read all Authors:


Read Author By Id:


Read Book By Id:


Delete Author By Id:


Delete Book By Id:


Final Project Structure:


Pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>springboot-graphql-crud-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-graphql-crud-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

Entity Class

Author.class

package com.knf.dev.demo.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "author")
public class Author implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name")
private String name;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}

Book.class

package com.knf.dev.demo.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "book")
public class Book implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name")
private String name;

@Column(name = "price")
private Double price;

@ManyToOne
@JoinColumn(name = "author_id", nullable = false, updatable = false)
private Author author;

public Author getAuthor() {
return author;
}

public void setAuthor(Author author) {
this.author = author;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

}

Repository

AuthorRepository.class

package com.knf.dev.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.knf.dev.demo.entity.Author;

public interface AuthorRepository extends JpaRepository<Author, Long> {

}

BookRepository.class

package com.knf.dev.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.knf.dev.demo.entity.Book;

public interface BookRepository extends JpaRepository<Book, Long> {

}

Mutation Resolver

Mutations allow us to modify server-side data, and it also returns an object based on the operation performed. It can be used to insert, update, or delete data.

package com.knf.dev.demo.resolver;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.knf.dev.demo.entity.Author;
import com.knf.dev.demo.entity.Book;
import com.knf.dev.demo.repository.AuthorRepository;
import com.knf.dev.demo.repository.BookRepository;

@Component
public class Mutation implements GraphQLMutationResolver {
@Autowired
private AuthorRepository authorRepository;

@Autowired
private BookRepository bookRepository;

public Author addAuthor(String name) {
Author author = new Author();
author.setName(name);

return authorRepository.saveAndFlush(author);
}

public Author updateAuthor(Long id, String name) {
Author author = new Author();
author.setId(id);
author.setName(name);

return authorRepository.saveAndFlush(author);
}

public Boolean deleteAuthor(Long id) {
authorRepository.deleteById(id);
return true;
}

public Book addBook(String name, Double price, Long author_id) {
Author author = authorRepository.findById(author_id).
orElseGet(null);
Book book = new Book();
book.setName(name);
book.setPrice(price);
book.setAuthor(author);
return bookRepository.saveAndFlush(book);
}

public Book updateBook(Long id, String name, Double price) {
Book book = new Book();
book.setId(id);
book.setName(name);
book.setPrice(price);
return bookRepository.saveAndFlush(book);
}

public Boolean deleteBook(Long id) {
bookRepository.deleteById(id);
return true;
}

}

Query Resolver

The Query for reading data from GraphQL APIs.

package com.knf.dev.demo.resolver;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.knf.dev.demo.entity.Author;
import com.knf.dev.demo.entity.Book;
import com.knf.dev.demo.repository.AuthorRepository;
import com.knf.dev.demo.repository.BookRepository;

@Component
public class Query implements GraphQLQueryResolver {

@Autowired
private AuthorRepository authorRepository;

@Autowired
private BookRepository bookRepository;

public Iterable<Book> allBooks() {
return bookRepository.findAll();
}

public Book book(Long id) {
return bookRepository.findById(id).orElseGet(null);
}

public Iterable<Author> allAuthors() {
return authorRepository.findAll();
}

public Author author(Long id) {
return authorRepository.findById(id).orElseGet(null);
}
}

GraphQL Schema(schema.graphqls)

type Query {
allAuthors: [Author]
allBooks: [Book]
book(id: ID!): Book
author(id: ID!): Author
}

type Mutation {
addAuthor(name: String!): Author!
updateAuthor(id: ID!, name: String!): Author!
deleteAuthor(id: ID!): Boolean
addBook(name: String!, price: Float!, author_id: ID!): Book!
updateBook(id: ID!, name: String!,price: Float!): Book!
deleteBook(id: ID!): Boolean
}

type Author {
id: ID
name: String!
}

type Book {
id: ID
name: String!
price: Float!
author: Author!
}

Driver Class

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringGraphqlCrudExampleApplication {

public static void main(String[] args) {
SpringApplication.
run(SpringGraphqlCrudExampleApplication.class, args);
}

}

Run

$ mvn spring-boot:run 

Popular posts from this blog

Spring boot video streaming example-HTML5

Spring Boot + OpenCSV Export Data to CSV Example

DataTable-Pagination example with Spring boot, jQuery and ajax

Spring boot web project free download:User Registration System

Spring Boot + Mockito simple application with 100% code coverage

ReactJS - Bootstrap - Buttons

10 Best Job Posting Sites 2021-2022

Spring Boot + JPA/Hibernate One to Many mapping example

Spring Boot Export data to PDF example

Java - Blowfish Encryption and decryption Example