Home  >  Article  >  Java  >  Build APIs and query systems using Spring Boot and GraphQL

Build APIs and query systems using Spring Boot and GraphQL

WBOY
WBOYOriginal
2023-06-22 11:31:221422browse

As the complexity of modern applications continues to increase, building scalable APIs and query systems has become increasingly important. In the past, REST API and SOAP were the mainstream API building solutions, but now GraphQL has also become a popular option. This article will introduce how to use Spring Boot and GraphQL to build an API and query system.

What is GraphQL?

GraphQL is a query language for APIs and query systems. Compared with traditional REST APIs, GraphQL has the following advantages:

  • Flexibility: GraphQL allows clients to specify the data they need, so unnecessary data transmission can be avoided.
  • Extensibility: GraphQL provides a high degree of flexibility to clients and servers, so new fields or operations can be added easily.
  • Performance: Because GraphQL allows clients to specify the data they need, excessive pulling of data can be avoided.

Spring Boot and GraphQL

Spring Boot is a Java framework for building Java-based web applications. It provides many useful features such as automatic configuration and rapid development. Compared with traditional Java web development, Spring Boot can make the development process more enjoyable and efficient.

In this article, we will use Spring Boot and GraphQL to build a basic API and query system. Before you get started, you need to know the following components:

  • Spring Boot: used to build Java-based web applications.
  • GraphQL Java: Java’s GraphQL implementation.
  • Spring Boot Starter Data JPA: Used to integrate Spring Boot and Java Persistence API (JPA).
  • H2 Database: In-memory database for local development and testing.

Building API and query system

First, we need to create a Spring Boot application. You can use Spring Initializr to quickly create a Spring Boot application. Here are the steps to create a Spring Boot application:

  • Open the Spring Initializr website.
  • Select your Spring Boot version.
  • You can choose your favorite build tool, such as Maven or Gradle.
  • Add required dependencies. In this article, we need "Spring Web", "GraphQL Java Tools", "GraphQL Java Spring Boot Starter", "Spring Boot Starter Data JPA" and "H2 Database".
  • Click the "Generate" button and the basic Spring Boot application structure will be downloaded.

Creating a GraphQL Schema

Before creating a GraphQL Schema, let’s think about what our API needs to do. We will create an API with three types: author, book, and author-book relationship. The following are our API operations:

  • Get the author list: Return the author list.
  • Get author by ID: Return author details by author ID.
  • Get the book list: Return the book list.
  • Get books by ID: Return book details by book ID.
  • Get the author-book relationship list: Return the author-book relationship list.
  • Get associated books by author ID: Return all book details of the author by author ID.

The next step is to create the GraphQL Schema. Schema defines the operations that can be performed on the API. In this article, we will use GraphQL Java Tools to create Schema. The steps to create GraphQL Schema are as follows:

  • Create a file named "schema.graphqls" in the src/main/resources folder and add the following code:
type Author {
  id: ID!
  name: String!
}

type Book {
  id: ID!
  title: String!
  author: Author!
}

type Relationship {
  id: ID!
  author: Author!
  book: Book!
}

type Query {
  authors: [Author]
  author(id: ID!): Author
  books: [Book]
  book(id: ID!): Book
  relationships: [Relationship]
  booksByAuthor(authorId: ID!): [Book]
}

This Schema defines three types: author, book and relationship. It also defines six operations: get author list, get author by ID, get book list, get books by ID, get relationship list and get associated books by author ID.

  • Create a GraphQL service in the project and load the schema.graphqls file into the service. Create a new class named "GraphQLProvider" in the src/main/java/com.example.demo folder, which contains the following code:
package com.example.demo;

import com.example.demo.entity.*;
import com.example.demo.repository.*;
import com.example.demo.resolver.*;

import java.util.List;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeRuntimeWiring;
import graphql.servlet.GraphQLServlet;
import graphql.servlet.SimpleGraphQLHttpServlet;

@Configuration
public class GraphQLProvider {
    private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLProvider.class);

    private final AuthorRepository authorRepository;
    private final BookRepository bookRepository;
    private final RelationshipRepository relationshipRepository;
    private List<DataFetcher> fetchDataers;

    @Autowired
    public GraphQLProvider(
      AuthorRepository authorRepository,
      BookRepository bookRepository,
      RelationshipRepository relationshipRepository,
      List<DataFetcher> fetchDataers
    ) {
        this.authorRepository = authorRepository;
        this.bookRepository = bookRepository;
        this.relationshipRepository = relationshipRepository;
        this.fetchDataers = fetchDataers;
    }

    @PostConstruct
    public void setup() {
        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return authorRepository.findAll();
            }
        });

        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return authorRepository.findById(environment.getArgument("id")).get();
            }
        });

        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return bookRepository.findAll();
            }
        });

        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return bookRepository.findById(environment.getArgument("id")).get();
            }
        });

        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return relationshipRepository.findAll();
            }
        });

        fetchDataers.add(new DataFetcher() {
            @Override
            public Object get(DataFetchingEnvironment environment) {
                return bookRepository.findByAuthor_Id(environment.getArgument("authorId"));
            }
        });
    }

    @Bean
    public GraphQLSchema schema() {
        SchemaParser schemaParser = new SchemaParser();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        TypeRuntimeWiring.Builder authorWiring = newTypeWiring("Author").dataFetchers(fetchDataers);

        return schemaGenerator.makeExecutableSchema(schemaParser.parse(getClass().getResource("/schema.graphqls").getPath()), RuntimeWiring.newRuntimeWiring()
          .type(authorWiring)
          .build());
    }

    @Bean
    public GraphQLServlet graphQLServlet() {
        return new SimpleGraphQLHttpServlet(new GraphQL.Builder(schema()).build());
    }
}

This class creates a GraphQL service and adds the schema The .graphqls file is loaded into the service and Data Fetchers are defined. Data Fetchers are responsible for fetching data and populating it with the results of GraphQL operations.

Create JPA Entities and Repository

Now, we need to create the entities and map them into the database. In this article, we will create Author, Book and Relationship entities and map them to H2 database using JPA.

  • Create a new interface named "AuthorRepository" in the src/main/java/com.example.demo.repository package, which contains the following code:
package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.entity.Author;

@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {
}
  • Follow the above method to create BookRepository and RelationshipRepository.
  • Create entities and relationships in the src/main/java/com.example.demo.entity package. The following is the sample code for the Author entity:
package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;

@Data
@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    protected Author() {}

    public Author(String name) {
        this.name = name;
    }
}

In the above example, we have created a Java entity named Author using the "id" and "name" fields of Lombok's @Data annotation.

  • Enter books and relationships.

Filling data

We can now populate the data using the H2 console or writing Java code.

Use H2 console to populate data:

  • 在src/main/resources文件夹中创建一个名为“data.sql”的文件,并添加以下代码:
INSERT INTO author (id, name) VALUES (1, 'William Shakespeare');
INSERT INTO author (id, name) VALUES (2, 'John Milton');
INSERT INTO author (id, name) VALUES (3, 'Charles Dickens');

INSERT INTO book (id, title, author_id) VALUES (1, 'Hamlet', 1);
INSERT INTO book (id, title, author_id) VALUES (2, 'Paradise Lost', 2);
INSERT INTO book (id, title, author_id) VALUES (3, 'Oliver Twist', 3);

INSERT INTO relationship (id, author_id, book_id) VALUES (1, 1, 1);
INSERT INTO relationship (id, author_id, book_id) VALUES (2, 2, 2);
INSERT INTO relationship (id, author_id, book_id) VALUES (3, 3, 3);
  • 启动应用程序并访问http://localhost:8080/h2-console。
  • 在H2控制台中,更改JDBC URL为jdbc:h2:mem:testdb并单击Connect按钮。
  • 执行data.sql文件中的查询以填充数据。

使用Java代码填充数据:

  • 在src/main/java/com.example.demo.seed包中创建一个新类并命名为“DataSeed”,其中包含以下代码:
package com.example.demo.seed;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.example.demo.entity.Author;
import com.example.demo.entity.Book;
import com.example.demo.entity.Relationship;
import com.example.demo.repository.AuthorRepository;
import com.example.demo.repository.BookRepository;
import com.example.demo.repository.RelationshipRepository;

@Component
public class DataSeed implements CommandLineRunner {

    private AuthorRepository authorRepository;
    private BookRepository bookRepository;
    private RelationshipRepository relationshipRepository;

    public DataSeed(AuthorRepository authorRepository,
                    BookRepository bookRepository,
                    RelationshipRepository relationshipRepository) {
        this.authorRepository = authorRepository;
        this.bookRepository = bookRepository;
        this.relationshipRepository = relationshipRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        Author shakespeare = new Author("William Shakespeare");
        Author milton = new Author("John Milton");
        Author dickens = new Author("Charles Dickens");

        authorRepository.save(shakespeare);
        authorRepository.save(milton);
        authorRepository.save(dickens);

        Book hamlet = new Book("Hamlet", shakespeare);
        Book paradiseLost = new Book("Paradise Lost", milton);
        Book oliverTwist = new Book("Oliver Twist", dickens);

        bookRepository.save(hamlet);
        bookRepository.save(paradiseLost);
        bookRepository.save(oliverTwist);

        relationshipRepository.save(new Relationship(shakespeare, hamlet));
        relationshipRepository.save(new Relationship(milton, paradiseLost));
        relationshipRepository.save(new Relationship(dickens, oliverTwist));
    }
}

在上面的示例中,我们创建了一个CommandLineRunner工具类,它在应用程序启动时添加示例数据到数据库中。

测试GraphQL API

我们现在可以使用GraphQL Playground工具查询GraphQL API。

以下是一些示例查询:

获取作者列表:

query {
  authors {
    id
    name
  }
}

按ID获取作者:

query {
  author(id: 1) {
    id
    name
  }
}

获取书籍列表:

query {
  books {
    id
    title
    author {
      id
      name
    }
  }
}

按ID获取书籍:

query {
  book(id: 1) {
    id
    title
    author {
      id
      name
    }
  }
}

获取作者-书籍关系列表:

query {
  relationships {
    id
    author {
      id
      name
    }
    book {
      id
      title
    }
  }
}

按作者ID获取关联书籍:

query {
  booksByAuthor(authorId: 1) {
    id
    title
    author {
      id
      name
    }
  }
}

结论

本文介绍了如何使用Spring Boot和GraphQL构建API和查询系统,并执行基本的操作。可以使用GraphQL Java Tools和JPA轻松定义Schema和映射实体。GraphQL的灵活性和可扩展性使得它成为构建现代Web应用程序的理想选择。

The above is the detailed content of Build APIs and query systems using Spring Boot and GraphQL. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn