GraphQL我的理解是,原来传统restful返回的json,只能是服务端返回来什么,客户端调用什么,而GraphQL的优势就是,由客户端来决定,我要什么参数,你服务端给我返什么参数。这是获取数据主动权的变更吧我个人认为。
这里记录一下GraphQL和springboot+mybatis整合的过程,方便以后查看,如有错误或者不足的地方,欢迎指出。
首先添加GraphQL依赖
<dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-spring-boot-starter</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>com.graphql-java</groupId> <artifactId>graphiql-spring-boot-starter</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.9</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.4</version> </dependency>
controller层代码
package top.glory.controller; import static graphql.Scalars.GraphQLInt; import static graphql.Scalars.GraphQLString; import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; import static graphql.schema.GraphQLObjectType.newObject; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import graphql.GraphQL; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import graphql.schema.GraphQLArgument; import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLList; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLSchema; import top.glory.pojo.User; import top.glory.service.UserService; @RestController public class GraphQLController { @Autowired private UserService userService; @GetMapping("/testGetGraphQL") public Object testGetGraphQL(String query){ //查询全部(主子表 这里是一张user表,一张book表) List<User> list = userService.findAllUserAndBook(); //创建book查询type GraphQLObjectType bookType = newObject() .name("book") .field(newFieldDefinition() .name("bid") .type(GraphQLInt)) .field(newFieldDefinition() .name("userid") .type(GraphQLInt)) .field(newFieldDefinition() .name("bookname") .type(GraphQLString)) .field(newFieldDefinition() .name("bookprice") .type(GraphQLInt)) .build(); //创建user查询type GraphQLObjectType userType = newObject() .name("user") .field(newFieldDefinition() .name("id") .type(GraphQLInt)) .field(newFieldDefinition() .name("username") .type(GraphQLString)) .field(newFieldDefinition() .name("password") .type(GraphQLString)) .field(newFieldDefinition() .name("book") //这里是子表的type name .type(new GraphQLList(bookType))) //这里是字表的type .build(); //获取请求参数中id GraphQLFieldDefinition personDefinition = GraphQLFieldDefinition.newFieldDefinition() .name("user") .type(userType) .argument(GraphQLArgument.newArgument().name("id").type(GraphQLInt)) .dataFetcher(new DataFetcher() { public Object get(DataFetchingEnvironment dataFetchingEnvironment) { int id = dataFetchingEnvironment.getArgument("id"); for (User user : list) { if (user.getId() == id) { return user; } } return null; } }) .build(); //创建schema,用于执行查询 GraphQLSchema schema = GraphQLSchema.newSchema() .query(newObject() .name("userQuery") .field(personDefinition) .build()) .build(); //传入schema,执行查询 GraphQL graphQL = GraphQL.newGraphQL(schema).build(); //返回查询结果集 Object data = graphQL.execute(query).getData(); return data; } }
接下来是service层和dao层,这里就不在列举,查询就是两张表联查
映射文件sql语句
<select id="findAllUserAndBook" resultMap="usermap"> SELECT * FROM USER LEFT JOIN book ON user.id = book.userid </select>
<resultMap type="top.glory.pojo.User" id="usermap"> <id property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <collection property="book" ofType="top.glory.pojo.Book"> <id property="bid" column="bid"/> <result property="userid" column="userid"/> <result property="bookname" column="bookname"/> <result property="bookprice" column="bookprice"/> </collection> </resultMap>
这里附上数据库脚本
/* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50536 Source Host : localhost:3306 Source Database : school Target Server Type : MYSQL Target Server Version : 50536 File Encoding : 65001 Date: 2018-05-11 17:54:28 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for book -- ---------------------------- DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `bid` int(11) NOT NULL AUTO_INCREMENT, `userid` int(11) DEFAULT NULL, `bookname` varchar(255) DEFAULT NULL, `bookprice` float(5,2) DEFAULT NULL, PRIMARY KEY (`bid`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of book -- ---------------------------- INSERT INTO `book` VALUES ('1', '1', '葵花宝典', '5.22'); INSERT INTO `book` VALUES ('2', '1', '辟邪剑谱', '63.23'); INSERT INTO `book` VALUES ('3', '1', '独孤九剑', '999.99'); INSERT INTO `book` VALUES ('4', '2', '吸星大法', '656.32'); INSERT INTO `book` VALUES ('5', '2', '龙抓手', '999.99'); INSERT INTO `book` VALUES ('6', '3', '九阳神功', '3.00'); INSERT INTO `book` VALUES ('7', '3', '易筋经', '231.60'); INSERT INTO `book` VALUES ('8', '3', '西联剑典', '123.00'); INSERT INTO `book` VALUES ('9', '3', '妈卖批', '999.99'); INSERT INTO `book` VALUES ('10', '1', 'ppp', '12.56'); -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', '张三', '123'); INSERT INTO `user` VALUES ('2', '李四', '1234'); INSERT INTO `user` VALUES ('3', '王五', '123123');
接下来就是测试了
这是我的测试路径,修改为自己的端口和方法即可。
query是参数名,后面是参数值,这里用get方式请求。
http://127.0.0.1:8888/testGetGraphQL?query={user(id:1){id,username,password,book{bid,bookname}}}
可以修改参数,http://127.0.0.1:8888/testGetGraphQL?query={user(id:1){id,username,book{bookname}}}