上篇:最近火起的 Bean Searcher 与 MyBatis Plus 倒底有啥区别?
介绍
Bean Searcher 是一款专注高级查询的只读 ORM,天生支持联表,免 DTO/VO 转换,使一行代码实现复杂列表检索成为可能!
我们可以像用 基础组件 ORM 那样使用 它,同时可以拥有 接近低代码 的开发效率。
使用场景
Bean Searcher 专克非事务性的复杂检索需求,例如:
- 普通后端查询
- 动态检索方式
- 动态分组查询
以上场景 Bean Searcher 都可以一行代码实现后端代码。
设计思想(出发点)
开发效率可以极大提升的原因
框架性能
性能不是主要卖点,但也比传统 ORM 框架平均提升 2 ~ 5 倍(Java 层性能)
代码仓库
- Github: github.com/troyzhxu/be…
- Gitee: gitee.com/troyzhxu/be…
文档与博客
新版本 v3.8.0 的变更
1、提升数据库兼容性
新增 参数转换器 机制,使 Oracle、PgSql 等数据库也同 MySQL 般顺滑。
2、参数构建器支持 自定义 SQL 条件
自定义 SQL 条件,只能在后端通过参数构建器使用,例如
Map<String, Object> params = MapUtils.builder()
// 生成 SQL 条件:u.id in (select user_id from xxx)
.field(User::getId).sql("$1 in (select user_id from xxx)")
.build();
List<User> users = searcher.searchList(User.class, params);
用 $n
来表示所需引用的第 n
个字段,再如:
Map<String, Object> params = MapUtils.builder()
// 生成 SQL 条件:id < 100 or age > 10
.field(User::getId, User::getAge).sql("$1 < 100 or $2 > 10")
.build();
List<User> users = searcher.searchList(User.class, params);
也可以在自定义的 SQL 片段中使用参数占位符 ?
(作为 JDBC 参数),例如:
Map<String, Object> params = MapUtils.builder()
// 生成 SQL 条件:id < ? or age > ?,两个占位符参数分别为:100,10
.field(User::getId, User::getAge).sql("$1 < ? or $2 > ?", 100, 10)
.build();
List<User> users = searcher.searchList(User.class, params);
3、分组动态查询条件生成机制
- 分组字段 生成
where
条件,其它字段 生成having
条件
例如一个指定了 groupBy
的 SearchBean:
@SearchBean(
tables = "student_course",
groupBy = "course_id" // 按课程 ID 分组
)
public class CourseScore {
@DbField("course_id")
private long courseId;
@DbField("sum(score)") // 该课程的总分(聚合函数:sum)
private long totalScore;
}
当以 courseId
为条件时:
Map<String, Object> params = MapUtils.builder()
.field(CourseScore::getCourseId, 101).op(LessThan.class)
.build();
List<CourseScore> list = searcher.searchList(CourseScore.class, params);
执行 SQL(条件在 where 里):
select course_id, sum(score) from student_course where course_id < 101 group by course_id
当以 totalScore
为条件时:
Map<String, Object> params = MapUtils.builder()
.field(CourseScore::getTotalScore, 500).op(GreateThan.class)
.build();
List<CourseScore> list = searcher.searchList(CourseScore.class, params);
执行 SQL(条件在 having 里):
select course_id, sum(score)
from student_course
group by course_id
having sum(score) > 500
当然两者还可以组合:
Map<String, Object> params = MapUtils.builder()
.field(CourseScore::getCourseId, 101).op(LessThan.class)
.field(CourseScore::getTotalScore, 500).op(GreateThan.class)
.build();
List<CourseScore> list = searcher.searchList(CourseScore.class, params);
执行 SQL:
select course_id, sum(score)
from student_course
where course_id < 101
group by course_id
having sum(score) > 500
4、新增 NotLike 运算符
目前内置的运算符已经有 19 个:
运算符 | 缩写 | SQL 片段 | 是否忽略空值 | 含义 |
---|---|---|---|---|
Equal |
eq |
x = ? |
是 | 等于(是缺省默认的运算符) |
NotEqual |
ne |
x != ? |
是 | 不等于 |
GreaterThan |
gt |
x > ? |
是 | 大于 |
GreaterEqual |
ge |
x >= ? |
是 | 大于等于 |
LessThan |
lt |
x < ? |
是 | 小于 |
LessEqual |
le |
x <= ? |
是 | 小于等于 |
Between |
bt |
x between ?1 and ?2 / x >= ?1 / x <= ?2 |
是 | 在...之间(范围查询) |
NotBetween |
nb |
x not between ?1 and ?2 / x < ?1 / x > ?2 |
是 | 不在...之间(范围查询)(since v3.3) |
Contain |
ct |
x like '%?%' |
是 | 包含(模糊查询)(since v3.2) |
StartWith |
sw |
x like '?%' |
是 | 以...开头(模糊查询) |
EndWith |
ew |
x like '%?' |
是 | 以...结尾(模糊查询) |
OrLike |
ol |
x like ?1 or x like ?2 or ... |
是 | 模糊或匹配(可有多个参数值)(since v3.7) |
NotLike |
nk |
x not like ? |
是 | 反模糊匹配(since v3.8) |
InList |
il / mv |
x in (?, ?, ...) |
是 | 多值查询(InList / il 自 v3.3 新增,之前是 MultiValue / mv ) |
NotIn |
ni |
x not in (?, ?, ...) |
是 | 多值查询(since v3.3) |
IsNull |
nl |
x is null |
否 | 为空(since v3.3) |
NotNull |
nn |
x is not null |
否 | 不为空(since v3.3) |
Empty |
ey |
x is null or x = '' |
否 | 为空(仅适用于 字符串 类型的字段) |
NotEmpty |
ny |
x is not null and x != '' |
否 | 不为空(仅适用于 字符串 类型的字段) |
5、优化注解省略机制
原本若要在实体类字段上省略 @DbFeild
时,必须满足以下三条件之一:
- 实体类省略了
@SearchBean
注解 - 实体类的
@SearchBean
没有指定tables
属性 - 实体类的
@SearchBean
指定了autoMapTo
属性
在 v3.8.0
之前,tables
与 autoMapTo
必须 同时出现 或 同时消失 才可以省略 @DbFeild
注解,例如改成这样即可:
@SearchBean(tables="user", autoMapTo="user")
public class UserVO {
private Long id; // 省略注解 @DbFeild
private Long name; // 省略注解 @DbFeild
}
但是总有小伙伴,不想不想省略 tables
,又不想指向 autoMapTo
,写成这样:
@SearchBean(tables="user")
public class UserVO {
private Long id; // 省略注解 @DbFeild
private Long name; // 省略注解 @DbFeild
}
结果让不少人都收到了异常,参考:github.com/ejlchina/be…
为了让大家少踩坑,v3.8.0
让这也兼容了这种的写法。现在要省略 @DbFeild
,只需满足以下四个条件之一即可:
- 实体类省略了
@SearchBean
注解 - 实体类的
@SearchBean
没有指定tables
属性 - 实体类的
@SearchBean.tables
只含一张表(since v3.8.0) - 实体类的
@SearchBean
指定了autoMapTo
属性
6、其它变更
其它变更就不一一列列举了,大家可以在这里查看:
未来特性
如果觉得不错,点个 Star 吧:
- Github: github.com/troyzhxu/be…
- Gitee: gitee.com/troyzhxu/be…
请大家继续关注,感谢一路走来支持 Bean Searcher 的你们,我们会努力做到更好。