graphQL与数据库、web整合及实现graphql分页,动态传参

数据库中的数据:https://blog.csdn.net/qq_26896085/article/details/104843889

mapper包下

EmployeeMapper.java

这里使用了Mybatis-plus,如果只是对单表进行查询,接口继承BaseMapper即可

package com.woodie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.woodie.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

// 这里通过想在.xml文件中写sql语句的方式查询数据则必须使用@Mapper注解
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
    // 这个接口继承了BaseMapper,则其包含了mybatis-plus定义的方法
    // 通过在xml中写sql,通过这里的方法查询数据
    Employee queryById();

}

实体类

Employee .java

package com.woodie.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.*;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("employees")
public class Employee {
    // 指定表的id
    // 通过type = IdType.AUTO设置id的自动增长, 由于表employees没有设置id为自动增长,因此这里不能设置这个参数,否则报错
    //@TableId(value = "emp_no", type = IdType.AUTO)
    @TableId(value = "emp_no")
    Integer empNo;
    Date birthDate;
    String firstName;
    String lastName;
    Date hireDate;
    String gender;
}

Pagination.java 

用于存放 分页时的数据的总条数,当前页面,当前页面的数据条数,总页

package com.woodie.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Pagination {
    Long current;
    Long pageSize;
    Long total;
    Long totalPage;
}

 TableResult.java

用于存放返回数据

package com.woodie.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TableResult<T> {
    List<T> list;
    Pagination pagination;
}

EmployeeServiceImpl .java

用于查询数据库

package com.woodie.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woodie.dao.EmployeeDao;
import com.woodie.entity.Employee;
import com.woodie.mapper.EmployeeMapper;
import com.woodie.service.EmployeeService;
import com.woodie.vo.Pagination;
import com.woodie.vo.TableResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;


    @Override
    public Employee queryById(int id) {
//        return employeeMapper.queryById();
        return  employeeMapper.selectById(id);
    }

    @Override
    public TableResult<Employee> queryListByPage(int page, int size) {
        Page employeePage = new Page(page, size);
        IPage<Employee> iPage = this.employeeMapper.selectPage(employeePage, null);
        Pagination pagination = Pagination.builder().current(iPage.getCurrent()).pageSize(iPage.getSize()).total(iPage.getTotal()).totalPage(iPage.getPages()).build();
        List<Employee> list = iPage.getRecords();
        TableResult<Employee> tableResult = new TableResult<>();
        tableResult.setList(list);
        tableResult.setPagination(pagination);
        return tableResult;
    }


}

DateScalarType.java

这个类用于自定义graphql查询的标量,自定义的标量为Date,用于处理数据中的日期数据

package com.woodie.modifyoriginal;

import graphql.schema.*;

import java.text.SimpleDateFormat;
import java.util.Date;

// 需要继承GraphQLScalarType
public class DateScalarType extends GraphQLScalarType {

    public DateScalarType() {
        super("Date", "Date value", new Coercing<String, String>() {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            public String serialize(Object input) {
                return sdf.format(input);
            }

            public String parseValue(Object input) {
                return this.serialize(sdf.format(input));
            }

            public String parseLiteral(Object input) {
                if (!(input instanceof Date)) {
                    throw new CoercingParseLiteralException("Expected AST type 'Date' but was ");
                } else {
                    return sdf.format(input);
                }
            }
        });
    }
}

GraphQLProvider.java

用于提供graphql支持

package com.woodie.graphql;

import com.woodie.modifyoriginal.DateScalarType;
import graphql.GraphQL;
import graphql.Scalars;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;

/**
 * 实现的功能:将Graphql对象载入到Spring容器,并完成GraphQL对象的初始化功能
 */
@Component
public class GraphQLProvider {

    private GraphQL graphQL;

    @Autowired
    private List<MyDataFetcher> myDataFetchers;

    // 实现对graphql对象的初始化
    @PostConstruct
    public void init() throws Exception {
        try {
            InputStream inputStream = GraphQLProvider.class.getClassLoader().getResourceAsStream("employee.graphqls");

            String content = IOUtils.toString(inputStream, "UTF-8");

            this.graphQL = GraphQL.newGraphQL(buildGraphQLSchema(content)).build();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private GraphQLSchema buildGraphQLSchema(String content){
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(content);
        return new SchemaGenerator().makeExecutableSchema(typeRegistry,buildWiring());
    }

    private RuntimeWiring buildWiring(){
        return RuntimeWiring.newRuntimeWiring()
                .type("EmployeeQuery", builder -> {
                            for (MyDataFetcher myDataFetcher : myDataFetchers) {
                                builder.dataFetcher(myDataFetcher.filedName(), environment -> myDataFetcher.dataFetcher(environment));
                            }
                            return builder;
                        }
                )
                .scalar(new DateScalarType())
                .build();
    }

    @Bean
    public GraphQL graphQL(){
        return this.graphQL;
    }

}

MyDataFetcher.java

用于提供数据fileName, environment,当有新的查询时,实现这个接口即可,而不需要更改GraphQLProvider.java中的代码

package com.woodie.graphql;

import graphql.schema.DataFetchingEnvironment;

public interface MyDataFetcher {
    /**
     * GraphQL中查询的名称, 对应下面的employee
     *
     * type EmployeeQuery {
     *     employee(empNo:Int) : Employee
     * }
     * @return
     */
    String filedName();

    /**
     * 数据的查询
     * @param environment
     * @return
     */
    Object dataFetcher(DataFetchingEnvironment environment);
}

 EmployeeListPageGraphQL.java

用于批量查询employee中的数据, 并进行分页

package com.woodie.graphql;

import com.woodie.service.EmployeeService;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class EmployeeListPageGraphQL implements MyDataFetcher{

    @Autowired
    EmployeeService employeeService;

    @Override
    public String filedName() {
        return "employeeListPage";
    }

    @Override
    public Object dataFetcher(DataFetchingEnvironment environment) {
        Integer page = environment.getArgument("page");
        Integer size = environment.getArgument("size");
        if (null == page) {
            page = 1;
        }
        if (null == size) {
            size = 10;
        }
        return this.employeeService.queryListByPage(page, size);
    }
}

EmployeeGraphQL.java

通过id进行查询employee中的单条数据

package com.woodie.graphql;

import com.woodie.service.EmployeeService;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class EmployeeGraphQL implements MyDataFetcher{

    @Autowired
    EmployeeService employeeService;

    @Override
    public String filedName() {
        return "employee";
    }

    @Override
    public Object dataFetcher(DataFetchingEnvironment environment) {
        Integer id = environment.getArgument("empNo");
        return this.employeeService.queryById(id);
    }
}

EmployeeController.java

这里支持get,post两种请求,并支持graphql动态传参

package com.woodie.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import graphql.ExecutionInput;
import graphql.GraphQL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RequestMapping("employee")
@Controller
public class EmployeeController {

    @Autowired
    private GraphQL graphQL;

    /**
     * graphql 查询的实现
     * @param query
     * @return
     */
    @GetMapping
    @ResponseBody
    public Map<String, Object> query(@RequestParam("query")String query,
                                     @RequestParam(value = "variables", required = false) String variables,
                                     @RequestParam(value = "operationName", required = false) String operationName){
        Map<String, Object> variablesMap = new HashMap<>();
        if (StringUtils.isNotEmpty(variables)) {
            JSONObject json = JSON.parseObject(variables);
            for (String key : json.keySet()) {
                variablesMap.put(key, json.get(key));
            }
        }
        return getStringObjectMap(query, variablesMap, operationName);
    }

    @PostMapping
    @ResponseBody
    public Map<String, Object> postQuery(@RequestBody Map<String, Object> param){
        String query = (String) param.get("query");
        String operationName = (String) param.get("operationName");
        Map variablesMap = (Map) param.get("variables");
        return getStringObjectMap(query, variablesMap, operationName);
    }

    private Map<String, Object> getStringObjectMap(String query, Map variablesMap, String operationName) {
        // 查看源码,点击下面的graphQL.execute
        // ExecutionResult result = graphQL.execute(query);
        ExecutionInput executionInput = ExecutionInput.newExecutionInput()
                .query(query)
                .variables(variablesMap)
                .operationName(operationName)
                .build();
        return this.graphQL.execute(executionInput).toSpecification();
    }
}

employee.graphql配置文件

scalar Date
scalar Long
schema {
    query: EmployeeQuery
}
type EmployeeQuery {
    employee(empNo:Int) : Employee
    employeeListPage(page: Int, size: Int): TableResult
}
type Employee {
    empNo: Int
    birthDate: Date
    firstName: String
    lastName: String
    hireDate: Date
    gender: String
}
type TableResult {
    list: [Employee]
    pagination: Pagination
}
type Pagination {
    current: Long
    pageSize: Long
    total: Long
    totalPage: Long
}

启动类

package com.woodie;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
//@MapperScan("com.woodie.mapper")
public class SpringBootStart {

    /**
     * 使用mybatisplus的分页插件,
     * @return
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringBootStart.class, args);
    }
}

测试

1、post请求,参数写死,分页查询employee的list

2、post请求,动态传参,分页查询employee的list

3、get请求,参数写死,根据id进行查询信息

4、get请求,动态传参, 根据id进行查询信息

猜你喜欢

转载自blog.csdn.net/qq_26896085/article/details/104881737