IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 基于JPA体验GraphQL的组合查询能力 -> 正文阅读

[Java知识库]基于JPA体验GraphQL的组合查询能力

嗯,前端会一些后台的开发很是重要......

诺,后端如果会一点前端,也同样重要......

?

GraphQL

【后端同学】我们通常会写很多API,特别是业务成长期,产品希望保障良好的体验的时候,他们会要求后端组合一堆API来满足页面的刚刚好的要素需求。特别是如下图橙色部分的组合API,真的是一个噩梦。前端同学与后端同学一直会不停地纠结。

?

看我72般变化


【前端同学】我们通常会调用很多API,哪怕只是增加一个要素,我也要多调用一次接口。没办法页面要,后端有(无语的是他们分了好多个接口,有时候鉴权还不一样)。你说就这样,页面的体验,效率能怨我么?

?

前端开发的烦恼

于是架构师来了,我们做个组合,做个读写模型分析,抽取共性,做到需要的数据就触发查询,再对数据进行编排组合来满足前端的诉求。把大家拉来评审下,避免API风暴......

但,等等,是否应该做一个通用查询,如这样?

?

统一组合查询API

按需触发接口,组合数据供页面使用,这就是GraphQL面对的问题域。我识别GraphQL的特点如下:

  1. 立足于从产品经理角度看问题,某种意义上是为前端开发解决问题
  2. 提供了强大的语法来解释嵌套数据结果,基于强类型,提供了相应的一些质量保障
  3. 语言支持丰富,如下图

?

GraphQL支持的语言

其他不说了,按如下步骤,体验下Java的先。

pom.xml

这里是基于IDEA社区办,构建的一个Spring Cloud Alibaba web应用。 这里是使用JPA提供数据,依赖的组件列表如下:


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-spring-boot-starter -->
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java-tools -->
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>7.1.0</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.22</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

    </dependencies>

application.yml

# 应用服务 WEB 访问端口
server:
  port: 8080

spring:
  application:
    name: graphql_demo
  #jpa
  jpa:
    properties:
      hibernate:
        #dialect: org.hibernate.dialect.MySQL5Dialect
        hbm2ddl:
          auto: "update"
    show-sql: true
  #mysql
  datasource:
    url: "jdbc:mysql://www.my-soft.net.cn:3306/db_nav?useUnicode=true&characterEncoding=UTF-8"
    username: "user"
    password: "password"
    driver-class-name: "com.mysql.cj.jdbc.Driver"
    #druid
    # 主数据源,默认的
    type: "com.alibaba.druid.pool.DruidDataSource"

Entity

Hanzi

package com.example.demo.entity;

import lombok.Builder;
import lombok.Data;

import javax.persistence.*;

@Entity(name = "t_hanzi")
@Data
//@Builder
public class Hanzi {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="f_id",nullable=false)
    private Integer id;
    @Column(name="f_hanzi",nullable=false)
    private String hanzi;
    @Column(name="f_pinyin",nullable=false)
    private String pinyin;
    @Column(name="f_sound_url",nullable=false)
    private String soundUrl;
    @Column(name="f_meaning",nullable=false)
    private String meaning;
    @Column(name="f_example",nullable=false)
    private String example;
    @Column(name="f_create_time",nullable=false)
    private String createTime;
    @Column(name="f_modify_time",nullable=false)
    private String modifyTime;
    @Column(name="f_userid_create",nullable=false)
    private String useridCreate;
    @Column(name="f_userid_modify",nullable=false)
    private String useridModify;
    @Column(name="f_writing_url",nullable=false)
    private String writingUrl;
}

Ciyu

package com.example.demo.entity;

import lombok.Builder;
import lombok.Data;

import javax.persistence.*;

@Entity(name = "t_ciyu")
@Data
//@Builder
public class Ciyu {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="f_id",nullable=false)
    private Integer id;
    @Column(name="f_ciyu",nullable=false)
    private String ciyu;
    @Column(name="f_pinyin",nullable=false)
    private String pinyin;
    @Column(name="f_sound_url",nullable=false)
    private String soundUrl;
    @Column(name="f_meaning",nullable=false)
    private String meaning;
    @Column(name="f_example",nullable=false)
    private String example;
    @Column(name="f_create_time",nullable=false)
    private String createTime;
    @Column(name="f_modify_time",nullable=false)
    private String modifyTime;
    @Column(name="f_userid_create",nullable=false)
    private String useridCreate;
    @Column(name="f_userid_modify",nullable=false)
    private String useridModify;
    @Column(name="f_synonyms",nullable=false)
    private String synonyms;
    @Column(name="f_antonyms",nullable=false)
    private String antonyms;
    @Column(name="f_state",nullable=false)
    private Integer state;
}

repository

HanziRepository

package com.example.demo.entity;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface HanziRepository extends JpaRepository<Hanzi,Integer> {
    // @Query("from Hanzi d where d.hanzi=':hz' ")
    public List<Hanzi> findByHanziContains(@Param("hz") String hz);
}

CiyuRepository

package com.example.demo.entity;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

//@Repository
public interface CiyuRepository extends JpaRepository<Ciyu,Integer> {
    // @Query("from Ciyu d where d.ciyu like '%:hz%' ")
    public List<Ciyu> findByCiyuContains(@Param("hz") String hz);
}

Resolver

package com.example.demo.svc;

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.example.demo.data.Book;
import com.example.demo.data.HanziCiyu;
import com.example.demo.entity.Ciyu;
import com.example.demo.entity.CiyuRepository;
import com.example.demo.entity.Hanzi;
import com.example.demo.entity.HanziRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
@AllArgsConstructor
public class HzcyQueryResolver implements GraphQLQueryResolver {

    ///*
    @Resource
    HanziRepository objHanziRepository;
    @Resource
    CiyuRepository objCiyuRepository;
  
  public Hanzi findHz(String hz){
        try {
            List<Hanzi> lstHanzi = objHanziRepository.findByHanziContains(hz);

            if ((lstHanzi.size() == 0) || (lstHanzi == null)) {
                return null;
            }
            return lstHanzi.get(0);
        }catch (Exception exp){
            return null;
        }
    }


    public List<Ciyu> findCy(String hz){
        try {
            List<Ciyu> lstCiyu = objCiyuRepository.findByCiyuContains(hz);

            if ((lstCiyu.size() == 0) || (lstCiyu == null)) {
                return null;
            }
            return lstCiyu;
        }catch (Exception exp){
            return null;
        }
    }

    public HanziCiyu findHzcy(String hz) {

        try {
            List<Hanzi> lstHanzi = objHanziRepository.findByHanziContains(hz);

            if ((lstHanzi.size() == 0) || (lstHanzi == null)) {
                return null;
            }
            List<Ciyu> lstCiyu = objCiyuRepository.findByCiyuContains(hz);


            HanziCiyu res = HanziCiyu.builder()
                    .hz(lstHanzi.get(0))
                    .lstCiyu(lstCiyu)
                    .build();

            return res;
        }catch (Exception exp){
            return null;
        }


    }
    //*/

}

resource/graphql/*

root.graphqls

type Query{
    findHzcy(hz:String !) : HanziCiyu
    findHz(hz:String !) : Hanzi
    findCy(hz:String !) : [Ciyu]
}

schema.graphqls

type Hanzi{
    id : Int
    hanzi : String
    pinyin : String
    soundUrl : String
    meaning : String
    example : String
    createTime : String
    modifyTime : String
    useridCreate : String
    useridModify : String
    writingUrl : String
}
type Ciyu{
    id : Int
    ciyu : String
    pinyin : String
    soundUrl : String
    meaning : String
    example : String
    createTime : String
    modifyTime : String
    useridCreate : String
    useridModify : String
    synonyms : String
    antonyms : String
    state : Int
}

type HanziCiyu{
    hz : Hanzi
    lstCiyu : [Ciyu]
}

运行

http://127.0.0.1:8080/graphiql

可看到如下页面,直接输入想要调用的接口与需要接口给出的字段就行。

?

当然,前台使用时,应该用这个URL :
http://127.0.0.1:8080/graphql?query=

?

正式使用

这里用到了restful jpa,你也可以如此查询
http://127.0.0.1:8080/hanzis

?

如此这个图就成立了

?

理想的结构

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:07:52  更:2022-07-17 16:13:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 7:15:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码