SQL类是mybatis官方提供的一个sql构建器,官网上也有一些具体的使用案例:
https://mybatis.org/mybatis-3/zh/statement-builders.html
public String listUserWithRole(UserInfoDto userInfoDto) {
return new SQL(){
{
SELECT("tui.id, tui.name, tui.age, tui.address, tr.role_name roleName");
FROM("tb_user_info tui");
LEFT_OUTER_JOIN("tb_user_role tur on tui.id = tur.user_id");
LEFT_OUTER_JOIN("tb_role tr on tur.role_id = tr.id");
//也可以用下面这种写法
//LEFT_OUTER_JOIN("tb_user_role tur on tui.id = tur.user_id", "tb_role tr on tur.role_id = tr.id");
if(userInfoDto.getAddress() != null) {
WHERE("address = #{userInfoDto.address}");
}
if(userInfoDto.getName() != null) {
WHERE("name = #{userInfoDto.name}");
}
}
}.toString();
}
SQL本身的结构比较简单,继承自抽象类AbstractSQL
主要的逻辑还是放在了AbstractSQL这个类里面。
UPDATE、SET以及下面的SELECT等,就是我们在匿名类中执行的方法。可以看出,我们给这些方法传入的参数,都被收集了起来,放入了SQLStatement这个内部类对象里,也就是sql对象。
SQLStatement内部类相当于一个大的容器,收集我们传入的参数
比如我们执行下面的语句时,会被SQL构建器做一个拆分
update tb_user set name = 'admin', age = 18 where id = 18
tb_user 放入 tables集合中
name = ‘admin’ 以及 age=18 放入 set集合中
id = 18 放入 where集合中。
下面我们来完整的过一下流程,看看sql是如何构建的:
进入SELECT方法的内部
确实是一个拆分过程,将我们传入的参数,收集到sql集合中。
接下来就是 FROM、LEFT_OUTER_JOIN等语句的收集过程,最后调用toString方法。
这里的toString不太一样,它是整个sql构建过程的最终按钮,builder模式的最后build。
进入sql方法
传入sql方法的是StringBuilder,进入方法后,被装饰成了SafeAppendable。其实就是多了个非空检查,源码就不贴了。
SQL语句被简单地拆分成了四种类型:增删改查,按照分类传入不同的方法进行处理。
我们当前debug的语句是SELECT,所以进入selectSQL(builder)方法:
先检查是否有distinct关键字,随后按照语句执行的顺序,调用sqlClause:
比如我们的语句是:
............where name = 'admin' and age = 18............
where集合里就有两个数据 name = ‘admin’ 以及 age = 18,传入sqlClause就是对应的List<String>parts。
拼装的逻辑如下:
1、先是关键字加上左边界符(keyword + open):
where(
2、再加上parts集合中的第一个元素
where( name = ‘admin’
3、i = 1 进入第二次循环时,会加上分隔符(conjunction),“where”操作的分隔符是 “AND”(见 SqlClause的最后一个参数)
where(name = ‘admin’ AND age = 18
4、最后结尾的时候,加上右边界符
where(name = ‘admin’ AND age = 18 )
where语句就这么组装完成了。
其他的关键字流程也差不多,不赘述。