栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于JPA体验GraphQL的组合查询能力

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于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提供数据,依赖的组件列表如下:

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            com.graphql-java
            graphql-spring-boot-starter
            5.0.2
        

        
        
            com.graphql-java
            graphql-java-tools
            5.2.4
        
        
            org.projectlombok
            lombok
        

        
            com.graphql-java-kickstart
            graphiql-spring-boot-starter
            7.1.0
        


        
            org.springframework.boot
            spring-boot-starter-data-jpa
            2.4.0
        
        
            org.springframework.boot
            spring-boot-starter-data-rest
        
        
            com.alibaba
            druid
            1.1.22
        
        
            mysql
            mysql-connector-java
        

    
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 {
    // @Query("from Hanzi d where d.hanzi=':hz' ")
    public List 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 {
    // @Query("from Ciyu d where d.ciyu like '%:hz%' ")
    public List 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/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

 

如此这个图就成立了

 

理想的结构

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013423.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号