Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/zhuyb0614/graph-batis

GraphQL&Mybatis的绝妙搭配
https://github.com/zhuyb0614/graph-batis

database-access graphql graphql-java mybatis

Last synced: about 1 month ago
JSON representation

GraphQL&Mybatis的绝妙搭配

Awesome Lists containing this project

README

        

# graph-batis 不是一个框架,而是一种开发模式
GraphQL&Mybatis的绝妙搭配
* [GraphQL 中文文档](https://graphql.cn/)

## 场景痛点还原

针对一些后台,我们可能需要很多列表.

比如下面几个

| 教师名 | 所授科目 |
| ------ | -------- |
| 老唐 | 政治 |
| 老朱 | 音乐 |

| 学生名 | 班级 |
| ------ | -------- |
| 老孙 | 高三一班 |
| 老猪 | 高三一班 |
| 老沙 | 高三一班 |

| 班级 | 教师 | 学生 |
| -------- | ---- | ---- |
| 高三一班 | 老唐 | 老孙 |
| 高三一班 | 老唐 | 老猪 |
| 高三一班 | 老唐 | 老沙 |

| 班级 | 教师 | 科目 |
| -------- | ---- | ---- |
| 高三一班 | 老唐 | 政治 |
| 高三一班 | 老朱 | 音乐 |

还有其他等等类型的查询

小白:这么多列表,我们需要根据每个列表都写一个SQL吗?

大佬:是的,每个列表我们都需要都写一个单独的SQL.要查询最少的数据,减少数据库压力.

小白:写很多SQL好麻烦,占用了我很多开发时间,牺牲一下数据库,我写一个大SQL把所有数据都查出来吧?

大佬:你这样有点缺少职业道德啊.

小白:那让我怎么办?能不能写的又快,又能兼顾让数据库压力小一些?不想加班啊大哥.

大佬:如果你能知道前端要什么数据,可不可以只查他要的数据呢?我了解GraghQL是可以把前端要的数据结构告诉后端的.我们写一个过滤器把不要的字段都去掉,不就行了!

小白:完美!

## 性能优势
* 通过GraphQL前端可以向后台发送自己想要的数据结构,知道了前端具体要什么数据,我们就可以根据前端需要的结构查询最少的数据,减轻DB压力.
## 开发优势
* 开发时可以将所有(夸张比喻)关联关系的表统统写一个SQL里,graph-batis-core中的*CleanSqlInterceptor*,将根据前端发送的数据结构,将不需要的查询字段和表剔出.一次编写,处处使用!
## 效果演示

以下样例都只通过org.zhuyb.graphbatis.mapper.RoomDao#findAll方法定义的如下SQL,自动精简后查询.无需多次编写关联关系

```sql
SELECT
st.student_name,
st.student_id,
su.subject_id,
su.subject_name,
t.teacher_id,
t.teacher_name,
r.room_id,
r.room_name
FROM
t_room AS r
JOIN t_teacher_room AS tr ON tr.room_id = r.room_id
JOIN t_student AS st ON st.room_id = r.room_id
JOIN t_teacher AS t ON t.teacher_id = tr.teacher_id
JOIN t_subject AS su ON su.subject_id = t.subject_id
```

进入graph-batis-example目录执行 mvn spring-boot:run启动服务后,打开下方链接打开graphiql
http://localhost:8080/graphiql?query=%7B%0A%20%20findRooms%20%7B%0A%20%20%20%20roomId%0A%20%20%20%20roomName%0A%20%20%20%20teachers%7B%0A%20%20%20%20%20%20teacherName%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A

![](./img/graphiQLV2.png)

实际执行SQL

```sql
SELECT
t.teacher_id,
t.teacher_name,
r.room_id,
r.room_name
FROM
t_room AS r
JOIN t_teacher_room AS tr ON tr.room_id = r.room_id
JOIN t_teacher AS t ON t.teacher_id = tr.teacher_id
```

http://localhost:8080/graphiql?query=%7B%0A%20%20findRooms%20%7B%0A%20%20%20%20roomId%0A%20%20%20%20roomName%0A%20%20%20%20students%7B%0A%20%20%20%20%20%20studentId%0A%20%20%20%20%20%20studentName%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A

![](./img/graphiQL2V2.png)

实际执行SQL

```sql
SELECT
st.student_name,
st.student_id,
r.room_id,
r.room_name
FROM
t_room AS r
JOIN t_student AS st ON st.room_id = r.room_id
```

## 启动引导

### 目录介绍

|-- graph-batis-core (Mybatis interceptor包,实际项目引用依赖)
|-- graph-batis-dependencies (Maven dependencyManagement依赖包版本约束)
|-- graph-batis-example (示例项目)
| |-- graph-batis-example-core (DAO层接口定义)
| |-- graph-batis-example-jooq (DAO层JOOQ实现示例)
| |-- graph-batis-example-mybatis (DAO层MyBatis实现示例)
|-- graph-batis-generator (代码生成器)

### 运行环境

1. jdk1.8+
2. mysql5.7+

### 启动流程(以graph-batis-example-mybatis演示)

打开application.properties修改spring.datasource各配置为本地数据库连接配置,项目已接入flayway无需手动初始化数据库数据.

直接main方法启动或者在graph-batis-example-mybatis目录下使用maven命令mvn sprintboot:run启动都可以.

首次正常启动后可以看到数据库中已经初始化数据.

启动成功后日志将打印graphiql和voyager路径如下

[Graphiql URL http://127.0.0.1:8080/graphiql]

[Voyager URL http://127.0.0.1:8080/voyager]

## TODO

- [x] 代码生成器提供
- [x] 去除VO,使其符合GraphQL规范
- [x] 查询缓存
- [x] 向上抽取抽象,使其通用化不局限GraphQL
- [x] 接入JOOQ
- [x] 扁平化查询
- [ ] 提供Client
- [ ] 接入Hibernate
- [ ] JDBC方式SQL改写
- [ ] 中间表voyager
- [ ] 分页
- [ ] 复杂条件查询

## MyBatis,JOOQ,Hibernate优缺点对比
### MyBatis
#### 优势
1. 对象映射,通过collection,association标签可以很直观的映射关联关系
2. SQL缓存,因为我们是直接解析的SQL所以很容易缓存固定的查询条件SQL

#### 劣势

1. 直接解析SQL无官方API