Spring Boot集成Graphql快速入门Demo

news2024/11/27 12:46:43

1.Graphql介绍

GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

优势

  1. GraphQL 速度快,并且比较稳定,GraphQL 的操作是在数据层面的,所以比较快。

  2. GraphQL 可以获取更多的资源,当查询一个数据的时候,不止是这个数据,甚至可以很快地查询到数据引用的另一个数据。GraphQL 可以在单个请求中去获取尽量多的数据,并且在弱网状态下,GraphQL 依旧表现出色。

  3. GraphQL 是单端点查询,并在此端点中去完成所有的查询。

  4. GraphQL 的可持续性非常出色,无论是新字段、还是旧字段,它都能很好地去处理,可维护性也极佳。

  5. GraphQL 具有向下兼容的特性,就算是很久很久以前的功能,GraphQL 还是能很好地去兼容它,保证旧版本的正常运行,同时又不影响新功能的加入以及整体的稳定性。这样做的好处就是,不需要去担忧版本号问题了。

  6. GraphQL 具有强类型,在 GraphQL 的查询中,一个级别对应一个强类型,这个类型充当一个字段的描述。这样的好处就是,在查询之前,可以校验出错误并提示,方便定位问题,提高性能。

  7. 自省:可以查询 GraphQL 服务器支持的类型。这为工具和客户端软件创建了一个强大的平台,可以在这些信息的基础上构建静态类型语言的代码生成、我们的应用程序框架、Relay 或 GraphiQL 等 IDE。

  8. GraphQL 支持使用者去决定服务器支持的类型。这样的好处就是,给很多使用 GraphQL 的 工具或者端建立了一个比较成熟且强大的应用平台,通过这个平台,一些框架、工具得到不断地优化提升。

劣势

  1. GraphQL 无法完成深度查询,所以无法对于未知深度的数据进行一次性查询。

  2. GraphQL 具有非常死板的响应结构,你必须遵从这个结构去查询数据,或者自己添加一个转换器来转换。

  3. GraphQL 无法进行网络级别的缓存,你必须使用另外别的办法进行持久查询。

  4. GraphQL 默认没有上传文件的功能,GraphQL 也不接收文件类型的参数,但是你可以使用 REST 的方式进行上传文件,达到上传文件的目的。

  5. GraphQL 的执行是不可预测的,因为 GraphQL 太过于灵活了。

  6. 同样的一个简单的 API,GraphQL 会表现得很复杂,所以建议简单 API 使用 RSET。

2.mysql环境搭建

参考代码仓库里面的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);

3.代码工程

 实验目标

实现一个基于graphql查询的例子

实现过程

1. 定义Schema,Schema使用GraphQL Schema Definition Language (SDL)来定义

2. 实现Resolver,Resolver函数负责从数据源中获取请求的数据

3. 配置和启动GraphQL服务器 ,要启动GraphQL服务器,你需要安装相应的依赖和配置服务器

pomxml

<?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>

GraphQLQueryResolver

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
}

model

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;
    }
}

repository

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);
}

DemoApplication.java

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);
    }


}

application.yaml

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

4.测试

启动spring boot应用 打开postman,调用

http://127.0.0.1:8088/graphql 输入

query {
 allBook{
 id
 name
 pageCount
 }
 }

返回结果4e17233ae985cef2ace7a76ad62597a6.png

5.引用

  • https://www.cnblogs.com/zcqiand/p/18011513

  • http://www.liuhaihua.cn/archives/710416.html

  • https://graphql.org/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1590603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion 本地部署教程:详细步骤与常见问题解析

作为一位热衷于探索前沿AI技术的博主&#xff0c;近期我深度研究了Stable Diffusion模型的本地部署过程。在这篇教程中&#xff0c;我将详述从环境准备到模型运行的每个步骤&#xff0c;并针对常见的部署问题给出解决方案&#xff0c;帮助你顺利在本地开启Stable Diffusion的创…

pyplot+pandas实现操作excel及画图

1、安装jupyter lab pip install jupyterlab # 启动 建议在指定的项目文件夹下 开启cmd窗口并执行 jupyter lab 启动后会自动打开浏览器访问 2、安装依赖 pip install matplotlib pip install xlrd pip install pandas 3、读取excel import pandas as pddf pd.read_excel(hi…

C# Solidworks二次开发:几何公差IGot相关操作API详解

大家好&#xff0c;今天要介绍的是关于几何公差IGot相关操作的API。 几何公差之前没有讲过&#xff0c;具体API如下面所示&#xff1a; &#xff08;1&#xff09;第一个为GetText&#xff0c;这个API的含义为获取此几何公差的指定文本部分&#xff0c;下面是官方的具体解释&…

基于springboot实现医疗病历互换系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现医疗病历交互系统演示 摘要 进入21世纪&#xff0c;计算机技术迅速向着网络化的、集成化方向发展。传统的单机版应用软件正在逐渐退出舞台&#xff0c;取而代之的是支持网络、支持多种数据信息的新一代网络版应用软件&#xff0c;形成了信息化的社会。信息…

FluentUI系列 - 1 - 介绍第一个窗口

介绍一个QML的UI库&#xff0c;国人编写&#xff0c;作者也耍知乎。这个UI库确实好用&#xff0c;但是教程基本等于无&#xff0c;个人在使用中顺便记录一下学习内容。这玩意儿也有Pyside6的版本&#xff0c;有需要的可以查看PySide6-FluentUI-QML。 FluentUI库地址​github.c…

开关灯---一维数组

直接看题&#xff1a; 开关灯 此题用模拟的复杂度是O(n&#xff09; &#xff0c;其实有更优解就是用完全平方数。但是我不想在C中遇到数学。。。所以用模拟解。 把数组的类型设为bool类型即可&#xff01; AC代码&#xff1a; #include<bits/stdc.h> using namespace …

Unity TMP Inputfield 输入框 框选 富文本 获取真实定位

一、带富文本标签的框选是什么 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition&#xff0c;开始选择时的光标下标和当前光标下标 对于未添加富文本标签时&#xff0c;直接通过以上两个值&#xff0c;判断一下框选方向&#xff08;前向后/后向前&…

前端 接口返回来的照片太大 加载慢如何解决

现象 解决 1. 添加图片懒加载 背景图懒加载 对背景图懒加载做的解释 和图片懒加载不同&#xff0c;背景图懒加载需要使用 v-lazy:background-image&#xff0c;值设置为背景图片的地址&#xff0c;需要注意的是必须声明容器高度。 <div v-for"img in imageList&quo…

麒麟 V10 离线 安装 k8s 和kuboard

目录 安装文件准备 主机准备 主机配置 修改主机名&#xff08;三个节点分别执行&#xff09; 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 安装依赖包&#xff08;所有节点&#xff09; 系统参数设置(所有节点) 时间同步…

html 引入vue Element ui 的方式

第一种&#xff1a;使用CDN的方式引入 <!--引入 element-ui 的样式&#xff0c;--> <link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <!-- 必须先引入vue&#xff0c; 后使用element-ui --> <…

Pycharm通过配置隧道连接远程服务器

前言&#xff1a; 上篇有说到局域网windows和服务器互通的情况下连接远程pycharm&#xff0c;这次咱们来说下通过跳板机的方式连接服务器如何做到windows远程连接到服务器 1&#xff1a;设置SSH隧道或SSH代理 ssh -L localhost:LOCAL_PORT:FINAL_SERVER_IP:FINAL_SERVER_PORT…

【深度学习】深入探索卷积神经网络:从基础到先进架构”

卷积神经网络&#xff1a;深度学习的视觉之眼 在过去的十年中&#xff0c;深度学习已经彻底改变了我们处理和理解图像、视频及其他视觉媒体的方式。其中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;无疑是这一革命的核心。本文将带您深入了解CNN的基础知识、关键发展…

CentOS 8服务器搭建L2TP服务器(over IPsec)操作指南

正文共&#xff1a;1234 字 14 图&#xff0c;预估阅读时间&#xff1a;2 分钟 之前发过把我自己的服务器搬上公网的文章&#xff08;我用100块钱把物理服务器放到了公网&#xff0c;省了几万块&#xff01;&#xff09;&#xff0c;当时L2TP拨号用的是网络上的解决方案&#x…

MySQL 修改数据

目录 数据插入-insert 不指定列名插入&#xff1a; 插入整行数据 格式&#xff1a; 多行数据插入 格式&#xff1a; 指定列名插入 插入1行 插入多行 更新字段-update 语法&#xff1a; 删除表 语法&#xff1a; 案例&#xff1a; 数据插入-insert INSERT 将数据行…

c++命令行解析开源库cxxopts上手教程

文章目录 cxxopts快速入门1. cmake环境配置2. 定义解析的规则3. 使用例子 cxxopts 简介 cxxopts是一个轻量级的C命令行解析库&#xff0c;它提供了易于使用的API来定义和解析命令行选项。它支持多种类型的选项&#xff0c;并且允许用户自定义选项的处理逻辑。 项目地址&#x…

Unity中支持泰语--没有版权限制

在Unity中支持泰语主要涉及以下几个方面&#xff1a; 选择合适的字体&#xff1a;在Unity中&#xff0c;确保使用支持泰文字符的字体是至关重要的。例如&#xff0c;可以选择使用Noto Serif Thai字体&#xff0c;这是一个支持泰语的字体2。 处理Unity版本问题&#xff1a;某些…

【C++之queue的应用及模拟实现】

C学习笔记---014 C之queue的应用及模拟实现1、queue的简单介绍2、queue的简单接口应用3、queue的模拟实现3.1、queue的结构一般的构建3.2、queue的适配器模式构建3.3、queue的主要接口函数 4、queue的模拟实现完整代码4.1、一般方式4.2、泛型模式 5、queue巩固练习题5.1、最小栈…

软件开发安全备受重视,浙江某运营商引入CWASP认证课程,

​浙江省某大型运营商是一家实力雄厚、服务优质的通信运营商&#xff0c;致力于为全省用户提供优质、高效的通信服务。数字时代&#xff0c;该运营商顺应信息能量融合发展趋势&#xff0c;系统打造以5G、算力网络、能力中台为重点的新型信息基础设施&#xff0c;夯实产业转型升…

VUE_H5页面跳转第三方地图导航,兼容微信浏览器

当前项目是uniapp项目&#xff0c;若不是需要替换uni.showActionSheet选择api onMap(address , organName , longitude 0, latitude 0){var ua navigator.userAgent.toLowerCase();var isWeixin ua.indexOf(micromessenger) ! -1;if(isWeixin) {const mapUrl_tx "…

nacos服务器挂了之后springboot/springcloud服务会挂吗?不会挂(顺便深入源码分析nacos配置中心客户端核心功能实现)

文章目录 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09;展开nacos客户端源码找本地缓存配置相关文件客户端内存缓存客户端健康状态获取配置的实现 nacos挂了之后服务会挂吗&#xff1f;不会挂&#xff08;深入源码分析&#xff09; 展开nac…