Previous: What is the difference between the recently popular Bean Searcher and MyBatis Plus?
introduce
Bean Searcher is a read-only ORM that focuses on advanced queries. It naturally supports joint tables and avoids DTO/VO conversion, making it possible to realize complex list retrieval with one line of code!
We can use it like a basic component ORM , and at the same time have a development efficiency close to low-code.
scenes to be used
Bean Searcher addresses complex non-transactional retrieval requirements such as:
- Normal backend query
- Dynamic search method
- Dynamic group query
In the above scenarios, Bean Searcher can implement back-end code with one line of code.
Design thinking (starting point)
The reason why development efficiency can be greatly improved
Frame performance
Performance is not the main selling point, but it is also an average of 2 to 5 times better than traditional ORM frameworks (Java layer performance)
Details: gitee.com/troyzhxu/be…
code repository
- Github: github.com/troyzhxu/be…
- Gitee: gitee.com/troyzhxu/be…
Documentation and Blog
- Documentation: bs.zhxu.cn/
- Blog: juejin.cn/column/7028…
Changes in the new version v3.8.0
1. Improve database compatibility
Added parameter converter mechanism to make Oracle, PgSql and other databases as smooth as MySQL.
Reference: gitee.com/troyzhxu/be…
2. The parameter builder supports custom SQL conditions
自定义 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、其它变更
其它变更就不一一列列举了,大家可以在这里查看:
future features
- BEP 54: SQL Fragments within Annotations Support Conditional Templates
- BEP 55: SearchBean supports embedded objects and lists
If you feel good, click Star:
- Github: github.com/troyzhxu/be…
- Gitee: gitee.com/troyzhxu/be…
Please continue to pay attention, thank you for supporting Bean Searcher along the way, we will strive to do better.
Previous: What is the difference between the recently popular Bean Searcher and MyBatis Plus?