表达式编写
查询说明
easy-query在 java 的静态语言特性下,参考众多 C# ORM(efcore,freesql,sqlsugar...),和 java ORM(mybatis-plus,beetlsql...)实现了支持单表多表,复杂,嵌套的 sql 表达式,并且拥有强类型语法提示,可以帮助不想写 sql 的用户,有洁癖的用户多一个选择.
select
eq的select是用来终结当前表达式生成新的表达式的方式,简单理解为表示告诉框架当前表达式需要返回的结果是select的结果,如果您了解stream api那么可以简单的理解为其map操作
概念补充 说明!!!
eq这个 orm 与之前您认识的 java 其他 orm 不相同,这个 orm 实现了近乎 95%的 sql 功能,其中一个就是子查询嵌套,所谓的子查询嵌套就是将之前查询结果视作派生表或叫做内嵌视图,后续我们将其统一称其为内嵌视图,比如select .... from (select id,name from table where name like ?) t where t.id = ?这个 sql 的括号内的那一部分(select id,name from table where name like ?)我们称之为内嵌视图
所以我们可以很轻易的实现其他 orm 无法实现的
select ... from
(
select
key1,
key2,
count() as c,
avg() as a,
sum() as s
from
table
where
name like ?
group by
key1,
key2
) t1
left join table2 t2 on t1.key1 = t2.key1
where.....select 后置风格
和原生 SQL 不同,在eq提供的 DSL 中,使用的是select后置风格,这个风格多见于c#语言的orm中和stream api有一种异曲同工之处,那么为什么eq选择select后置?
- 强类型的 java 语言类型
select后置有助于推导表达式后续可操作的类,比如stream api select后置其实本质和书写 sql 是一样的,虽然你在编写 sql 的时候是 select 先写但是你在不写from group by等操作后是无法编写 select 的内容只能用*来代替,所以其实 sql 的书写本质也是select后置

说明!!!
这张图充分的说明了 sql 的执行过程和解析过程也是 eq 的书写过程,该执行流程中唯一能调换的就是
select和order by的顺序
每次 select 会对之前的表达式进行汇总生成
内嵌视图,对后续的 select 继续操作那么将对内嵌视图进行操作
其中6和7可以互相调换,如果先
select后order那么将会对内嵌视图进行排序,如果先order后select那么会先排序后生成内嵌视图但是因为内嵌视图后续没有操作所以会展开,即不生成内嵌视图
select语句出现在where,orderBy,groupBy,having等之后,如果表达式调用了select那么这个 sql 就是确定了的如果再次调用where那么前面的表达式将被视为派生表或内嵌视图,比如select .... from (select id,name from table ) t where t.id = ?每次select会对当前表达式进行一次结果集包装(派生表或内嵌视图)

我们以这个简单的例子为例可以看到我们应该编写的顺序是select在最后
easyEntityQuery.queryable(HelpProvince.class)
.where(o -> o.id().eq("1"))
.orderBy(o -> o.id().asc())
.select(o -> new HelpProvinceProxy()
.id().set(o.id())
.name().set(o.name())
)
//本质就是如下写法
// .select(o->{
// HelpProvinceProxy province= new HelpProvinceProxy();
// province.id().set(o.id());
// province.name().set(o.name());
// return province;
// })
//.select(o->o.FETCHER.id().name().fetchProxy())//如果返回结果一样可以用fetcher
// .select(o->new HelpProvinceProxy(){{//双大括号初始化方式返回
// id().set(o.id());
// name().set(o.name());
// }})
.toList();复杂的查询顺序
easyEntityQuery.queryable(HelpProvince.class) //1
.where(o->o.id().eq("1")) //2
.orderBy(o->o.id().asc()) //3
.select(o->new HelpProvinceProxy()//4
.id().set(o.id())
.name().set(o.name())
)
//.select(o->o.FETCHER.id().name().fetchProxy())//如果返回结果一样可以用fetcher
.where(o->o.id().eq("1")) // 5
.select(o->new HelpProvinceProxy()
.id().set(o.id())//6
)
.toList();注意点及说明!!!
select一般都是最后写的,在你没有写表的时候只能用 * 来代替,先写表确定,然后写条件写排序写分组等确定了之后写选择的select的列不写就是主表的*如果在写where就对前面的表进行括号进行匿名表处理以此类推
分解表达式
1
表达式:easyEntityQuery.queryable(HelpProvince.class)
sql:select * from help_province2
表达式:easyEntityQuery.queryable(HelpProvince.class).where(o->o.id().eq("1"))
sql:select * from help_province where id='1'3
表达式:easyEntityQuery.queryable(HelpProvince.class).where(o->o.id().eq("1")).orderBy(o->o.id().asc())
sql:select * from help_province where id='1' order by id asc4
表达式: easyEntityQuery.queryable(HelpProvince.class)
.where(o -> o.id().eq("1"))
.orderBy(o -> o.id().asc())
.select(o -> new HelpProvinceProxy()
.id().set(o.id())
.name().set(o.name())
)
sql:select id,name from help_province where id='1' order by id asc以select方法作为终结方法结束本次sql链式,后续的操作就是将select和之前的表达式转成匿名sql类似select * from (select * from help_province) t,其中select的简化操作o->o.FETCHER.id().name()不支持返回VO和后续链式,当且仅当返回结果为自身时用于快速选择列,如果需要支持后续链式请添加.fetchProxy()
5
表达式:easyEntityQuery.queryable(HelpProvince.class)
.where(o->o.id().eq("1"))
.orderBy(o->o.id().asc())
.select(o->new HelpProvinceProxy()
.id().set(o.id())
.name().set(o.name())
)//转成匿名表sql
.where(o->o.id().eq("1"))
sql:select * from (select id,name from help_province where id='1' order by id asc) t where t.id='1'6
表达式:easyEntityQuery.queryable(HelpProvince.class)
.where(o->o.id().eq("1"))
.orderBy(o->o.id().asc())
.select(o->new HelpProvinceProxy()
.id().set(o.id())
.name().set(o.name())
)//转成匿名表sql
.where(o->o.id().eq("1"))
.select(o->new HelpProvinceProxy()
.id().set(o.id())
)
sql:select id from (select id,name from help_province where id='1' order by id asc) t where t.id='1'链式说明!!!
select之前的所有操作比如多个where,多个orderby都是对之前的追加,limit是替换前面的操作多次limit获取最后一次
在entityQuery下groupBy不支持连续调用两个,groupBy之间必须存在一个select指定要查询的结果才可以,其他api下多次调用行为也是追加