Spring Boot整合GraphQL

news2024/11/24 23:06:00

RPC选型入门测试系列文章

GraphQL是一种用于API开发的查询语言和运行时环境。它由Facebook开发并于2015年开源。GraphQL的主要目标是提供一种更高效、灵活和易于使用的方式来获取和操作数据。与传统的RESTful API相比,GraphQL允许客户端精确地指定需要的数据,并减少了不必要的网络传输和数据处理。
采用GraphQL,甚至不需要有任何的接口文档,在定义了Schema之后,服务端实现Schema,客户端可以查看Schema,然后构建出自己需要的查询请求来获得自己需要的数据。

1、数据类型

1.1、标量类型
  1. Int -32位整型数字;
  2. Float-双精度浮点型;
  3. String-UTF‐8 字符序列;
  4. Boolean-布尔型,true 或者 false;
  5. ID-标识类型,唯一标识符,注意此ID为字符,如果使用Mysql自增长id,也会自动转为对应的字符串;
1.2. 高级数据类型
  1. Object - 对象,用于描述层级或者树形数据结构。Object类型有一个类型名,以及类型包含的字段。
type Product {
    id: ID!
    info: String!
    price: Float
}
12345

在此示例中,声明了Product对象类型,定义了3 个字段:
id:非空 ID 类型。
info:非空字符串类型。
price:浮点型。

  1. Interface-接口,用于描述多个类型的通用字;与 Object一样。
interface Product {
    id: ID!
    info: String!
    price: Float
}
12345
  1. Union-联合类型,用于描述某个字段能够支持的所有返回类型以及具体请求真正的返回类型;
  2. Enum-枚举,用于表示可枚举数据结构的类型;
enum Status {
  Yes
  No
}
type Product {
    id: ID!
    info: String!
    price: Float
    stat: Status
}
12345678910
  1. Input-输入类型input本质上也是一个type类型,是作为Mutation接口的输入参数。换言之,想要定义一个修改接口(add,update,delete)的输入参数对象,就必须定义一个input输入类型。
input BookInput {
    isbn: ID!
    title: String!
    pages: Int
    authorIdCardNo: String
}
123456
  1. List -列表,任何用方括号 ([]) 括起来的类型都会成为 List 类型。
type Product {
    id: ID!
    info: String
    price: Float
    images: [String]
}
123456
  1. Non-Null-不能为 Null,类型后边加!表示非空类型。例如,String 是一个可为空的字符串,而String!是必需的字符串。

基本操作

  • Query(只读操作)
#schema.graphqls定义操作
type Query {
    allBooks: [Book]!
    bookByIsbn(isbn: ID): Book
}

# 接口查询语法
query{
  allBooks {
    title
    author {
      name
      age
    }
  }
}
12345678910111213141516
  • Mutation(可写操作)
#schema.graphqls定义操作
type Mutation {
    createBook(bookInput: BookInput): Book
    createAuthor(authorInput: AuthorInput): Author
}

# mutation{
#   createAuthor(authorInput:{ 
#     idCardNo: "341234567891234567",
#     name:"test1",
#     age:38
#   }
#   ){
#     name 
#     age
#   }
# }

2、Spring Boot整合GraphQL

GraphQL只是一种架构设计,具体的实现需要各个技术平台自己实现,目前主流的开发语言基本都已经有现成的类库可以使用,GraphQL Java就是Java平台的实现。

spring-graphql中定义的核心注解如下:

  • @GraphQlController:申明该类是GraphQL应用中的控制器
  • @QueryMapping:申明该类或方法使用GraphQL的query操作,等同于@SchemaMapping(typeName = “Query”),类似于@GetMapping
  • @Argument:申明该参数是GraphQL应用的入参
  • @MutationMapping:申明该类或方法使用GraphQL的mutation操作,等同于@SchemaMapping(typeName = “Mutation”)
  • @SubscriptionMapping:申明该类或方法使用GraphQL的subscription操作,等同于@SchemaMapping(typeName = “Subscription”)
  • @SchemaMapping:指定GraphQL操作类型的注解,类似@RequestMapping
2.1、项目目录

项目代码目录
![在这里插入图片描述](https://img-blog.csdnimg.cn/9a7b5d2461224e378ad48dca2ba0baa0.jpeg#pic_center

2.3、GraphQL的schema.graphql

GraphQL对应的schema.graphql定义文件

schema {
    query: Query,
    mutation: Mutation,
}

type Query {
    getUserById(id:Int) : [User],
}

input UserInput {
    username : String,
    password : String,
    name : String,
}
type Mutation {
    createUser(userInput: UserInput): User,
    updateUser(id: Int!, userInput: UserInput): User,
    deleteUser(id: ID!): Int,

}
type User {
    id : ID!,
    username : String,
    password : String,
    name : String,
}
2.4、Java代码

pom.xml依赖包文件

	<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-graphql</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.23</version>
		</dependency>
		<dependency>
			<groupId>com.graphql-java</groupId>
			<artifactId>graphql-java-extended-scalars</artifactId>
			<version>19.1</version>
		</dependency>
	</dependencies>
</project>

对应的数据库实体类

package com.example.graphql.dao;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    private String name;

    public User(String username, String password, String name) {
        this.username = username;
        this.password = password;
        this.name = name;
    }
}


GraphQL对应的输入类

package com.example.graphql.dao;
import lombok.Data;
import java.time.OffsetDateTime;
@Data
public class UserInput {
    private String username;
    private String password;
    private String name;
}

操作数据库

在Spring Data JPA中使用JpaRepository接口类完成对数据库的操作

增加、修改

JpaRepository中,当保存的实体类主键ID在数据库中存在时进行修改操作,不存在则进行保存。

    @Autowired
    private UserInfoRepository userInfoRepository;

    public void addUserInfo() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId("jHfnKlsCvN");
        userInfo.setLoginName("登录名");
        userInfo.setPassword("123456");
        userInfo.setAge(18);
        // 保存或修改用户信息, 并返回用户实体类
        UserInfo save = userInfoRepository.save(userInfo);
    }
删除【根据实体类主键删除】
    @Autowired
    private UserInfoRepository userInfoRepository;

    public void deleteUserInfo() {
        // 根据实体类主键删除
        userInfoRepository.deleteById("111");
    }
查询
查询单个信息【findBy】

JpaRepository中根据某一个字段或者某几个字段查询时,就使用findBy方法。
这里给个例子,假设,我想根据loginName查询用户信息,就可以用findByLoginName查询用户信息,如果有多个条件后面就继续拼接AndXXX
假设,我想查询loginName等于某值,并且password等于某值的,就可以使用findByLoginNameAndPassword

public interface UserInfoRepository extends JpaRepository<UserInfo, String> {
	// 根据登录名查询用户信息
    UserInfo findByLoginName(String loginName);
    // 根据登录名和密码查询用户信息
    UserInfo findByLoginNameAndPassword(String loginName, String password);
}
查询多个信息【findAllBy】

JpaRepository中根据某一个字段或者某几个字段查询时,就使用findAllBy方法,而接口根据某个条件查询写法跟查询单个信息时一样。
这里给个例子,假设,我想查询loginName等于某值的所有用户信息时,就写做findAllByLoginName

public interface UserInfoRepository extends JpaRepository<UserInfo, String> {
	// 查询所有登录名叫做XXX的用户
	List<UserInfo> findAllByLoginName(String loginName);
}
对应的数据库操作类

```java
package com.example.graphql.servise.Repository;

import com.example.graphql.dao.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Service
@Repository
//必须声明事务,不然删除报错
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {
 
  List<User> findById(int id);
//  List<User> updateById(int id);
  int deleteById(int id);

}

对外服务接口类
在service层中实现查询和删除:

package com.example.graphql.servise;

import com.example.graphql.dao.User;
import com.example.graphql.servise.Repository.UserRepository;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

  @Resource
  private UserRepository userRepository ;
  
  public List<User> queryUser(int id) {
    List<User> user = userRepository.findById(id);
    return user;
  }
  public int deleteUser(int id) {
    int bool = userRepository.deleteById(id);
    return bool;
  }
}

在controller层中配置增删改查接口:

package com.example.graphql.controller;

import com.example.graphql.dao.User;
import com.example.graphql.dao.UserInput;
import com.example.graphql.servise.Repository.UserRepository;
import com.example.graphql.servise.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {


    @Resource
    private UserService userService;
    @Resource
    private UserRepository userRepository ;

    @QueryMapping
    public List<User> getUserById(@Argument int id) {
        return userService.queryUser(id);
    }

    @MutationMapping
    public int deleteUser(@Argument int id) {
        return userService.deleteUser(id);
    }

    @MutationMapping
    public User createUser(@Argument UserInput userInput) {
        User user = new User();
        System.out.println(userRepository);
        System.out.println(user);
        BeanUtils.copyProperties(userInput,user);
        userRepository.save(user);
        return user;
    }

    @MutationMapping
    public User updateUser(@Argument int id,@Argument UserInput userInput) {
        System.out.println(userInput);
        User user = new User();
        user.setId(id);
        BeanUtils.copyProperties(userInput,user);
        System.out.println(user);
        userRepository.save(user);
        return user;
    }
}

3、运行效果

3.1、添加用户

在这里插入图片描述

3.2、查询用户

在这里插入图片描述

3.3、更新用户

在这里插入图片描述

3.4、删除用户

在这里插入图片描述

4、总结

使用Spring for GraphQL试用了GraphQL后,它实现按需取数据的功能。服务器开发人员和前端开发人员可以通过schema.graphqls定义文件,协定好接口和数据,省掉写接口文档的工作。
客户端可以通过一次请求获取多个数据资源,而不需要发起多个请求。相对于传统的RESTful API,GraphQL的实现和后端处理逻辑可能更加复杂。需要编写解析器、验证查询、处理复杂的字段解析和数据获取等。

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

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

相关文章

C语言实例_stdlib.h库函数功能及其用法详解

一、前言 C语言作为一种高效、灵活的编程语言&#xff0c;标准库的使用对于开发人员来说是不可或缺的。其中&#xff0c;stdlib.h是C语言中一个重要的标准库头文件&#xff0c;提供了许多常用的函数和工具&#xff0c;以便开发人员能够更加便捷地进行内存管理、字符串处理、随…

《深入理解JAVA虚拟机笔记》运行时栈帧、方法分派、动态类型

运行时栈帧结构 Java 虚拟机以方法作为最基本的执行单元&#xff0c;“栈帧”&#xff08;Stack Frame&#xff09;则是用于支持虚拟机进行方法调用和方法执行背后的数据结构&#xff0c;它也是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了方法的局部变量表、操作数栈…

电气产品外壳常用材质PA、PC、PBT、ABS究竟是什么?

在如今工业制造领域&#xff0c;各种改性塑料、复合材料以及轻质合金材料的运用日趋成熟。在电气领域&#xff0c;不同电气产品的外壳、组件材质采用不同材料&#xff0c;以同为科技&#xff08;TOWE&#xff09;电气产品为例&#xff0c;工业连接器系列产品采用PA6外壳材质、机…

python+django网上购物商城系统o9m4k

语言&#xff1a;Python 框架&#xff1a;django/flask可以定制 软件版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发工具pycharm/vscode都可以 前端框架:vue.js 系统使用过程主要涉及到管理员和用户两种角色&#xff0c;主要包含个…

javascript实现数据双向绑定

ES5中的双向绑定 ES5中的对象属性类型有两种&#xff1a;分别是数据属性和访问器属性 一&#xff0c;数据属性 数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性 1&#xff0c;configurable:表示能否通过delete删除属性而重新定义…

利用Pandas进行高效网络数据获取

利用Pandas进行高效网络数据获取 背景&#xff1a; ​ 最近看到一篇关于使用Pandas模块进行爬虫的文章&#xff0c;觉得很有趣&#xff0c;这里为大家详细说明。 基础铺垫&#xff1a; ​ pd.read_html pandas 库中的一个函数&#xff0c;用于从 HTML 页面中读取表格数据并…

CEC2017(Python):五种算法(PSO、RFO、SSA、DE、HHO)求解CEC2017

一、5种算法简介 1、粒子群优化算法PSO 2、红狐优化算法RFO 3、麻雀搜索算法SSA 4、差分进化算法DE 5、哈里斯鹰优化算法HHO 二、CEC2017简介 参考文献&#xff1a; [1]Awad, N. H., Ali, M. Z., Liang, J. J., Qu, B. Y., & Suganthan, P. N. (2016). “Problem de…

详解“量子极限下运行的光学神经网络”——相干伊辛机

量子计算和量子启发计算可能成为解答复杂优化问题的新前沿&#xff0c;而经典计算机在历史上是无法解决这些问题的。 当今最快的计算机可能需要数千年才能完成高度复杂的计算&#xff0c;包括涉及许多变量的组合优化问题&#xff1b;研究人员正在努力将解决这些问题所需的时间缩…

白话机器学习的数学-2-分类

1、设置问题 图片分类&#xff1a;只根据尺寸把它分类为 纵向图像和横向图像。 如果只用一条线将图中白色的点和黑色的点分开&#xff1a; 这次分类的目的就是找到这条线。 2、内积 找到一条线&#xff0c;这是否意味着我们要像学习回归时那样&#xff0c;求出一次函数的斜率…

写在2023岁末:敏锐地审视量子计算的当下

本周&#xff0c;《IEEE Spectrum》刊登了一篇出色的文章&#xff0c;对量子计算&#xff08;QC&#xff09;的近期前景进行了深入探讨。 文章的目的并不是要给量子计算的前景泼冷水&#xff0c;而是要说明量子计算的前景还很遥远&#xff0c;并提醒读者量子计算的用例可能很窄…

【Minikube Prometheus】基于Prometheus Grafana监控由Minikube创建的K8S集群

文章目录 1. 系统信息参数说明2. Docker安装3. minikube安装4. kubectl安装5. Helm安装6. 启动Kubernetes集群v1.28.37. 使用helm安装Prometheus8. 使用helm安装Grafana9. Grafana的Dashboard设定10. 设定Prometheus数据源11. 导入Kubernetes Dashboard12. 实验过程中的常见问题…

RabbitMQ之快速入门、上手

前言 学习一样新技术、新框架&#xff0c;最重要的是学习其思想、原理。即原理性思维。 如果是因为工作原因&#xff0c;需要快速上手RabbitMQ&#xff0c;本篇或许适合你。 核心概念 Connection&#xff1a;publisher&#xff0f;consumer 和 broker 之间的 TCP 连接Channel…

亚信安慧AntDB数据并行加载工具的实现(一)

1.概述 数据加载速度是评判数据库性能的重要指标&#xff0c;能否提高数据加载速度&#xff0c;对文件数据进行并行解析&#xff0c;直接影响数据库运维管理效率。基于此&#xff0c;AntDB分布式数据库提供了两种数据加载方式&#xff1a; 一是类似于PostgreSQL的Copy命令&am…

java spring boot 自定义 aop

以一个锁的加锁和释放为例 1、先定义注解 /*** 锁切面* author fmj*/ Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface VersionLockAOP { }2、然后定义切面类以及切点 /*** 切面*/ Component Aspect Slf4j public class VersionLockAOPAspe…

GitHub Copilot 终极详细介绍

编写代码通常是一项乏味且耗时的任务。现代开发人员一直在寻找新的方法来提高编程的生产力、准确性和效率。 像 GitHub Copilot 这样的自动代码生成工具可以使这成为可能。 GitHub Copilot 到底是什么&#xff1f; GitHub Copilot 于 2021 年 10 月推出&#xff0c;是 GitHub 的…

idea配置docker推送本地镜像到远程私有仓库

目录 1&#xff0c;搭建远程Docker 私有仓库 Docker registry 2&#xff0c;Windows10/11系统上安装Docker Desktop 3&#xff0c;idea 配置远程私有仓库地址 4&#xff0c;idea 配置Docker 5&#xff0c;idea在本地构建镜像 6&#xff0c;推送本地Docker镜像到远程 Dock…

第3课 获取并播放音频流

本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88680079 FFmpeg作为一套庞大的音视频处理开源工具&#xff0c;其源码有太多值得研究的地方。但对于大多数初学者而言&#xff0c;如何快速利用相关的API写出自己想要的东西才是迫切需要…

USB -- STM32F103 USB VIDEO(视频)Camera同步传输讲解(九)

目录 链接快速定位 前沿 1 描述符修改 1.1 设备描述符修改 1.2 配置描述符修改 1.3 字符串描述符修改 1.4 编译报错修改 2 增加功能函数 2.1 Camera功能模块介绍 2.2 USB复位函数修改 2.3 Speaker_Data_Setup函数修改 2.4 非零端点函数修改 2.5 JEPG数据获取 3…

IDEA使用HDFS的JavaApi

注&#xff1a;以下代码操作是利用junit在java测试文件夹中实现。 1. 准备工作 1.1 创建测试类 创建测试类&#xff0c;并定义基本变量 public class HDFSJAVAAPI {// 定义后续会用到的基本变量public final String HDFS_PATH "hdfs://hadoop00/";Configuration …

骑砍战团MOD开发(27)-module_tableau_materials.py材质

一.配置材质资源 OpenBrf寻找对应材质资源. tableau配置材质资源 ("round_shield_1", 0, "sample_shield_round_1", 512, 256, 0, 0, 0, 0,[(store_script_param, ":banner_mesh", 1),(set_fixed_point_multiplier, 100),(init_position, pos1),…