检索参数
检索参数是 Bean Searcher 的重要检索信息,它们共同组成了 Searcher
接口的检索方法的 第二个 类型为 Map<String, Object>
的参数值。
分页参数
Bean Searcher 提供了两种分页:Page 分页 与 Offset 分页。
可配置项
在 Spring Boot 项目中,可在项目配置文件 application.properties
或 application.yml
中对分页进行个性化配置:
配置键名 | 含义 | 可选值 | 默认值 |
---|---|---|---|
bean-searcher.params.pagination.type | 分页类型 | page 、offset | page |
bean-searcher.params.pagination.default-size | 默认每页查询条数 | 正整数 | 15 |
bean-searcher.params.pagination.max-allowed-size | 每页最大查询条数 | 正整数 | 100 |
bean-searcher.params.pagination.page | 页码参数名(在 type = page 时有效) | 字符串 | page |
bean-searcher.params.pagination.size | 大小参数名(在 type = page 时有效) | 字符串 | size |
bean-searcher.params.pagination.offset | 偏移参数名(在 type = offset 时有效) | 字符串 | offset |
bean-searcher.params.pagination.max | 大小参数名(在 type = offset 时有效) | 字符串 | max |
bean-searcher.params.pagination.start | 起始页码 或 起始偏移量 | 自然数 | 0 |
Page 分页
Page 分页提供两个分页参数(参数名可配置):
page
: 页码size
: 每页查询条数
用法示例(默认配置下):
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.page(0, 15) // 该方法会自动使用正确的参数名
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
Offset 分页
Offset 分页也提供两个分页参数(参数名可配置):
offset
: 偏移量max
: 每页查询条数
用法示例(默认配置下):
Map<String, Object> params = new HashMap<>();
params.put("offset", 0); // 从第 0 条开始查
params.put("max", 15); // 每页 15 条
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.limit(0, 15) // 该方法会自动使用正确的参数名
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
起始 页码/偏移量
配置项 起始页码/偏移量(bean-searcher.params.pagination.start
)默认是 0
,在 Page 分页机制下,page
参数为 0 表示查询第 1 页。当把 起始页码 配置为 1
时,则 page
参数为 1 才表示查询第 1 页。Offset 分页同理。
最大查询条数
配置项 最大查询条数(bean-searcher.params.pagination.max-allowed-size
)默认是 100
,它可以风控一些恶意查询:比如黑客想通过一次查询 1 亿 条数据从而让我们系统崩溃时,Bean Searcher 会自动把它缩小为 100
。
默认分页大小
配置项 默认分页大小(bean-searcher.params.pagination.default-size
)默认是 15
,在用户为添加分页参数时,默认每页查询 15 条数据。
TIP
Searcher
实例的 searchAll(...)
方法不受分页参数影响
排序参数
可配置项
在 Spring Boot 项目中,可在项目的 application.properties
或 application.yml
文件中通过如下配置项对排序参数进行定制:
配置键名 | 含义 | 可选值 | 默认值 |
---|---|---|---|
bean-searcher.params.sort | 排序字段参数名 | 字符串 | sort |
bean-searcher.params.order | 排序方法参数名 | 字符串 | order |
用法示例(默认配置下):
Map<String, Object> params = new HashMap<>();
params.put("sort", "age"); // 按年龄字段排序
params.put("order", "desc"); // 降序
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.orderBy(User::getAge, "desc") // 该方法会自动使用正确的参数名
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
字段参数
字段参数是根据 SearchBean (检索实体类)里被 @DbField
注解的字段衍生出来的一系列参数,它们起到对查询结果进行筛选的作用。
可配置项
在 Spring Boot 项目中,可在项目的 application.properties
或 application.yml
文件中通过如下配置项对字段参数进行定制:
配置键名 | 含义 | 可选值 | 默认值 |
---|---|---|---|
bean-searcher.params.separator | 字段参数名分隔符 | 字符串 | - |
bean-searcher.params.operator-key | 字段运算符参数名后缀 | 字符串 | op |
bean-searcher.params.ignore-case-key | 是否忽略大小写字段参数名后缀 | 字符串 | ic |
字段衍生规则
示例,对于如下的一个 SearchBean:
@SearchBean(tables = "user")
public class User {
@DbField("name")
private String name;
// Getter and Setter ...
}
2
3
4
5
6
7
8
以它的 name
字段为例,可衍生出以下一系列的字段参数:
name-{n}
: name 字段的第 n 个参数值,如:name-0
、name-1
、name-2
等等name
: 等价于name-0
,name 字段的第 0 个参数值name-op
: name 的 字段运算符,如:Equal
、GreaterEqual
、GreaterThan
等等name-ic
: name 字段在检索时是否应该忽略大小写
以上在衍生字段参数时,用到了中划线(-
)作为连接符,如果你喜欢下划线(_
),可把 bean-searcher.params.separator
配置为下划线即可。配置为下划线后,衍生出的参数就是 name_{n}
、name
、name_op
、name_ic
了。同理: op
与 ic
后缀您也可以自定义。
TIP
字段参数,是根据 SearchBean 里的 JAVA 字段名(不是表字段)衍生出来的,已经和数据库的表字段解耦了。
字段运算符
字段运算符是用来描述某个字段的检索方式,即:SQL 的拼接方法。Bean Searcher 共提供了 13 种不同的字段运算符,下表:
运算符全称 | 运算符缩写 | SQL 片段 | 含义 |
---|---|---|---|
Equal | eq | = ? | 等于(是缺省默认的运算符) |
GreaterEqual | ge | >= ? | 大于等于 |
GreaterThan | gt | > ? | 大于 |
LessEqual | le | <= ? | 小于等于 |
LessThan | lt | < ? | 小于 |
NotEqual | ne | != ? | 不等于 |
Empty | ey | is null | 为空 |
NotEmpty | ny | is not null | 不为空 |
Include | in | like '%?%' | 包含(模糊查询) |
StartWith | sw | like '?%' | 以...开头(模糊查询) |
EndWith | ew | like '%?' | 以...结尾(模糊查询) |
Between | bt | between ? and ? 或 <= ? 或 >= ? | 在...之间(范围查询) |
MultiValue | mv | in (?, ?, ...) | 多值查询 |
由于 Bean Searcher 为运算符提供了全称与缩写,所以对于每一种运算符,都有三种等效的用法,例如,查询 name
等于 Jack 的用户:
Map<String, Object> params = new HashMap<>();
params.put("name", "Jack");
// 使用枚举变量
params.put("name-op", Equal.class);
// 查询满足条件的第一个用户
User jack = searcher.searchFirst(User.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "Jack").op(Equal.class)
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
12
13
等价于:
Map<String, Object> params = new HashMap<>();
params.put("name", 'Jack');
// 使用运算符名称
params.put("name-op", "Equal");
// 查询满足条件的第一个用户
User jack = searcher.searchFirst(User.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "Jack").op("Equal")
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
12
13
等价于:
Map<String, Object> params = new HashMap<>();
params.put("name", 'Jack');
// 使用运算符缩写
params.put("name-op", "eq");
// 查询满足条件的第一个用户
User jack = searcher.searchFirst(User.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "Jack").op("eq")
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
12
13
由于 Equal
是缺省默认的字段运算符,所以上述代码也等价于:
Map<String, Object> params = new HashMap<>();
params.put("name", 'Jack');
// 查询满足条件的第一个用户
User jack = searcher.searchFirst(User.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "Jack")
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
由于字段参数 name
是 name-0
的等价写法,所以上述代码还等价于:
Map<String, Object> params = new HashMap<>();
params.put("name-0", 'Jack');
// 查询满足条件的第一个用户
User jack = searcher.searchFirst(User.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "Jack")
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
内嵌参数
内嵌参数,即是:嵌入到实体类注解内的参数(参见:实体类 > 嵌入参数 章节),它可分为 普通内嵌参数 与 拼接参数,他们可以轻松处理各种复杂的 SQL 检索问题。
普通内嵌参数
普通内嵌参数,是以一个冒号(:
)前缀(形如 :name
)的形式嵌入到实体类注解的 SQL 片段中的参数。
例如,有这样的一个 SearchBean:
@SearchBean(
tables = "student",
joinCond = "age = :age"
)
public class Student {
@DbField("s.name")
private String name;
// Getter and Setter ...
}
2
3
4
5
6
7
8
9
10
11
则我们可以用如下方式检索年龄为 20 的学生:
Map<String, Object> params = new HashMap<>();
params.put("age", 20); // 指定内嵌参数 age 的值为 20
// 查询 年龄为 20 的学生
List<Student> students = searcher.searchList(Student.class, params);
// 使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field("age", 20)
.build();
User jack = searcher.searchFirst(User.class, params);
2
3
4
5
6
7
8
9
10
11
TIP
普通内嵌参数 最终会被 Bean Searcher 处理为一种 JDBC 参数,无需担心 SQL 注入问题。
拼接参数
拼接参数(since v2.1),是以一个冒号(:
)为前缀一个冒号(:
)为后缀(形如 :name:
)的形式嵌入到实体类注解的 SQL 片段中的参数。
拼接参数的用武之地非常广:能用 普通内嵌参数 的地方肯定能用 拼接参数,而 普通内嵌参数 搞不定的地方 拼接参数 则可以轻松搞定,它可以做到 动态生成 SQL。
参考:示例 > 动态检索 > 分表检索 案例。