赞
踩
GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。
GraphQL 速度快,并且比较稳定,GraphQL 的操作是在数据层面的,所以比较快。
GraphQL 可以获取更多的资源,当查询一个数据的时候,不止是这个数据,甚至可以很快地查询到数据引用的另一个数据。GraphQL 可以在单个请求中去获取尽量多的数据,并且在弱网状态下,GraphQL 依旧表现出色。
GraphQL 是单端点查询,并在此端点中去完成所有的查询。
GraphQL 的可持续性非常出色,无论是新字段、还是旧字段,它都能很好地去处理,可维护性也极佳。
GraphQL 具有向下兼容的特性,就算是很久很久以前的功能,GraphQL 还是能很好地去兼容它,保证旧版本的正常运行,同时又不影响新功能的加入以及整体的稳定性。这样做的好处就是,不需要去担忧版本号问题了。
GraphQL 具有强类型,在 GraphQL 的查询中,一个级别对应一个强类型,这个类型充当一个字段的描述。这样的好处就是,在查询之前,可以校验出错误并提示,方便定位问题,提高性能。
自省:可以查询 GraphQL 服务器支持的类型。这为工具和客户端软件创建了一个强大的平台,可以在这些信息的基础上构建静态类型语言的代码生成、我们的应用程序框架、Relay 或 GraphiQL 等 IDE。
GraphQL 支持使用者去决定服务器支持的类型。这样的好处就是,给很多使用 GraphQL 的 工具或者端建立了一个比较成熟且强大的应用平台,通过这个平台,一些框架、工具得到不断地优化提升。
GraphQL 无法完成深度查询,所以无法对于未知深度的数据进行一次性查询。
GraphQL 具有非常死板的响应结构,你必须遵从这个结构去查询数据,或者自己添加一个转换器来转换。
GraphQL 无法进行网络级别的缓存,你必须使用另外别的办法进行持久查询。
GraphQL 默认没有上传文件的功能,GraphQL 也不接收文件类型的参数,但是你可以使用 REST 的方式进行上传文件,达到上传文件的目的。
GraphQL 的执行是不可预测的,因为 GraphQL 太过于灵活了。
同样的一个简单的 API,GraphQL 会表现得很复杂,所以建议简单 API 使用 RSET。
参考代码仓库里面的mysql模块,这里只贴出docker-compose.yml
- version: '3'
- services:
- mysql:
- image: registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql:5.7
- container_name: mysql_3306
- restart: unless-stopped
- volumes:
- - "./mysql/my.cnf:/etc/mysql/my.cnf"
- - "./mysql/init-file.sql:/etc/mysql/init-file.sql"
- - "./mysql/data:/var/lib/mysql"
- # - "./mysql/conf.d:/etc/mysql/conf.d"
- - "./mysql/log/mysql/error.log:/var/log/mysql/error.log"
- - "./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d" # init sql script directory -- tips: it can be excute when `/var/lib/mysql` is empty
- environment: # set environment,equals docker run -e
- TZ: Asia/Shanghai
- LANG: en_US.UTF-8
- MYSQL_ROOT_PASSWORD: root # set root password
- MYSQL_DATABASE: demo # init database name
- ports: # port mappping
- - "3306:3306"
运行
docker-compose -f docker-compose.yml -p mysql5.7 up -d
初始化脚本
- CREATE DATABASE IF NOT EXISTS `BOOK_API_DATA`;
- USE `BOOK_API_DATA`;
-
-
- CREATE TABLE IF NOT EXISTS `Book` (
- `id` int(20) NOT NULL AUTO_INCREMENT,
- `name` varchar(255) DEFAULT NULL,
- `pageCount` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `Index_name` (`name`)
- ) ENGINE=InnoDB AUTO_INCREMENT=235 DEFAULT CHARSET=utf8;
-
-
- CREATE TABLE `Author` (
- `id` INT(20) NOT NULL AUTO_INCREMENT,
- `firstName` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
- `lastName` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
- `bookId` INT(20) NULL DEFAULT NULL,
- PRIMARY KEY (`id`) USING BTREE,
- UNIQUE INDEX `Index_name` (`firstName`) USING BTREE,
- INDEX `FK_Author_Book` (`bookId`) USING BTREE,
- CONSTRAINT `FK_Author_Book` FOREIGN KEY (`bookId`) REFERENCES `BOOK_API_DATA`.`Book` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
- )
- COLLATE='utf8_general_ci'
- ENGINE=InnoDB
- AUTO_INCREMENT=6
- ;
-
-
-
-
-
-
- INSERT INTO `Book` (`id`, `name`, `pageCount`) VALUES (1, 'the golden ticket', '255');
- INSERT INTO `Book` (`id`, `name`, `pageCount`) VALUES (2, 'coding game', '300');
-
-
- INSERT INTO `Author` (`id`, `firstName`, `LastName`, `bookId`) VALUES (4, 'Brendon', 'Bouchard', 1);
- INSERT INTO `Author` (`id`, `firstName`, `LastName`, `bookId`) VALUES (5, 'John', 'Doe', 2);
实现一个基于graphql查询的例子
1. 定义Schema,Schema使用GraphQL Schema Definition Language (SDL)来定义
2. 实现Resolver,Resolver函数负责从数据源中获取请求的数据
3. 配置和启动GraphQL服务器 ,要启动GraphQL服务器,你需要安装相应的依赖和配置服务器
- <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>springboot-demo</artifactId>
- <groupId>com.et</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
-
- <artifactId>GraphQL</artifactId>
-
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- <kotlin.version>1.5.0</kotlin.version>
- </properties>
- <dependencies>
-
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>com.graphql-java-kickstart</groupId>
- <artifactId>graphql-spring-boot-starter</artifactId>
- <version>12.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
-
-
- <dependency>
- <groupId>com.graphql-java-kickstart</groupId>
- <artifactId>graphql-java-tools</artifactId>
- <version>12.0.0</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
-
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>26.0-jre</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.apache.tomcat.embed</groupId>
- <artifactId>tomcat-embed-jasper</artifactId>
- <scope>provided</scope>
- </dependency>
- </dependencies>
- </project>
- package com.et.graphql.queryresolvers;
-
-
- import com.et.graphql.model.Author;
- import com.et.graphql.model.Book;
- import com.et.graphql.repository.AuthorRepository;
- import com.et.graphql.repository.BookRepository;
- import graphql.kickstart.tools.GraphQLQueryResolver;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
-
-
-
-
- @Component
- public class BookQuery implements GraphQLQueryResolver{
-
-
- @Autowired
- BookRepository bookRepository;
- @Autowired
- AuthorRepository authorRepository;
-
-
- public Iterable<Book> allBook(){
- return bookRepository.findAll();
- }
-
-
- public Book getBookByName(String name){
- return bookRepository.findBookByName(name);
- }
-
-
- public Iterable<Author> allAuthor(){
- return authorRepository.findAll();
- }
-
-
- }
- package com.et.graphql.queryresolvers;
-
-
- import com.et.graphql.model.Book;
- import com.et.graphql.repository.BookRepository;
- import graphql.kickstart.tools.GraphQLMutationResolver;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
-
-
- import java.util.Optional;
-
-
- @Component
- public class BookMutation implements GraphQLMutationResolver {
-
-
- @Autowired
- BookRepository bookRepository;
-
-
- public Book newBook(String name, String pageCount){
- Book book = new Book();
- book.setName(name);
- book.setPageCount(pageCount);
- return bookRepository.save(book);
- }
-
-
- public Book deleteBook(Integer id){
- Book deleteBook = new Book();
- Optional<Book> findBook = bookRepository.findById(id);
- if(findBook.isPresent()){
- bookRepository.delete(findBook.get());
- deleteBook = findBook.get();
- }
- return deleteBook;
- }
- }
- package com.et.graphql.queryresolvers;
-
-
-
-
- import com.et.graphql.model.Author;
- import com.et.graphql.model.Book;
- import com.et.graphql.repository.AuthorRepository;
- import graphql.kickstart.tools.GraphQLResolver;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
-
-
- @Component
- public class BookAuthorResolver implements GraphQLResolver<Book> {
-
-
- @Autowired
- AuthorRepository authorRepository;
-
-
- public Author getAuthor(Book book){
-
-
- return authorRepository.findAuthorByBookId(book.getId());
- }
- }
graphqls(/resources/graphql)
type Book { id: Int name: String pageCount: String author: Author } type Query { allBook: [Book] allAuthor:[Author] getBookByName(name: String): Book } type Mutation { newBook(name: String!, pageCount: String): Book deleteBook(id:Int!):Book } type Author { id: Int firstName: String lastName: String bookId: Int }
- package com.et.graphql.model;
-
-
-
-
- import javax.persistence.*;
-
-
- @Entity
- @Table(name = "Author", schema = "BOOK_API_DATA")
- public class Author {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- Integer id;
- @Column(name = "firstname")
- String firstName;
- @Column(name = "lastname")
- String lastName;
- @Column(name = "bookid")
- Integer bookId;
-
-
- public Author(Integer id, String firstName, String lastName, Integer bookId) {
- this.id = id;
- this.firstName = firstName;
- this.lastName = lastName;
- this.bookId = bookId;
- }
-
-
- public Author() {
-
-
- }
-
-
- public Integer getId() {
- return id;
- }
-
-
- public String getFirstName() {
- return firstName;
- }
-
-
- public String getLastName() {
- return lastName;
- }
-
-
- public void setId(Integer id) {
- this.id = id;
- }
-
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
-
- public Integer getBookId() {
- return bookId;
- }
-
-
- public void setBookId(Integer bookId) {
- this.bookId = bookId;
- }
- }
- package com.et.graphql.model;
-
-
- import javax.persistence.*;
-
-
- @Entity
- @Table(name = "Book", schema = "BOOK_API_DATA")
- public class Book {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- private Integer id;
- private String name;
- @Column(name = "pagecount")
- private String pageCount;
-
-
- public Book(Integer id, String name, String pageCount) {
- this.id = id;
- this.name = name;
- this.pageCount = pageCount;
- }
-
-
- public Book() {
-
-
- }
-
-
- public Integer getId() {
- return id;
- }
-
-
- public void setId(Integer id) {
- this.id = id;
- }
-
-
- public String getName() {
- return name;
- }
-
-
- public void setName(String name) {
- this.name = name;
- }
-
-
- public String getPageCount() {
- return pageCount;
- }
-
-
- public void setPageCount(String pageCount) {
- this.pageCount = pageCount;
- }
- }
- package com.et.graphql.repository;
-
-
- import com.et.graphql.model.Author;
- import org.springframework.data.repository.CrudRepository;
-
-
- public interface AuthorRepository extends CrudRepository<Author, Integer> {
-
-
- Author findAuthorByBookId(Integer bookId);
- }
- package com.et.graphql.repository;
-
-
-
-
- import com.et.graphql.model.Book;
- import org.springframework.data.repository.CrudRepository;
-
-
- public interface BookRepository extends CrudRepository<Book, Integer> {
-
-
- Book findBookByName(String name);
- }
- package com.et.graphql;
-
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.ComponentScan;
-
-
- @SpringBootApplication
- @ComponentScan(basePackages = "com.et.graphql.queryresolvers")
- public class BookAPIApplication {
-
-
- public static void main(String[] args) {
- SpringApplication.run(BookAPIApplication.class, args);
- }
-
-
- }
- spring.jpa.hibernate.ddl-auto=none
- spring.jpa.database=mysql
- spring.jpa.open-in-view=true
- spring.jpa.show-sql=true
- server.port=8088
- #logging.level.org.hibernate=DEBUG
- logging.level.org.hibernate.SQL=DEBUG
- spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
- spring.jpa.hibernate.use-new-id-generator-mappings= false
-
-
- # book api db"
- spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
- spring.datasource.username=root
- spring.datasource.password=root
以上只是一些关键代码,所有代码请参见下面代码仓库
https://github.com/Harries/springboot-demo
启动spring boot应用 打开postman,调用
http://127.0.0.1:8088/graphql 输入
- query {
- allBook{
- id
- name
- pageCount
- }
- }
返回结果
https://www.cnblogs.com/zcqiand/p/18011513
http://www.liuhaihua.cn/archives/710416.html
https://graphql.org/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。