通用查询条件
1. FlexQuery 动态查询
1.1 单模型查询
// SELECT name, code FROM table WHERE name = 'PM' AND code = '001'
FlexQuery flexQuery = new FlexQuery()
.select("name", "salary")
.where(new Filters().eq("name", "PM").eq("code", "001"));
// 等价于:
flexQuery = new FlexQuery()
.select(Job::getName, Job::getSalary)
.where(new Filters().eq(Job::getName, "PM").eq(Job::getCode, "001"));
// 执行查询
List<Job> jobs = this.searchList(flexQuery);
专业代码写法:
private List<DesignAppVersion> getHistoricalVersion(Long envId) {
List<String> fields = ListUtils.getLambdaFields(
DesignAppVersion::getName,
DesignAppVersion::getAppId,
DesignAppVersion::getLocked,
DesignAppVersion::getPublished);
Filters filters = new Filters().eq(DesignAppVersion::getEnvId, envId)
.eq(DesignAppVersion::getLocked, false);
FlexQuery flexQuery = new FlexQuery().select(fields).where(filters);
return this.searchList(flexQuery);
}
1.2 关联查询 OneToMany 数据
假设部门 Department 模型定义如下,其中 employees 和 positions 是两个 OneToMany 字段:
public class Department {
private String name;
private List<Employee> employees;
private List<Position> positions;
}
要查询指定 ID 的部门,同时返回部门下的所有员工和所有岗位数据:
SubQueries subQueries = new SubQueries().expand(Department::getEmployees)
.expand(DesignModel::getPositions);
Department dept = this.getById(id, subQueries);
其它示例:
// 获取导入模板时,同时获取该模板下的导入字段列表
SubQueries subQueries = new SubQueries().expand(ImportTemplate::getImportFields);
ImportTemplate importTemplate = importTemplateService.getById(templateId, subQueries);
2. Filters 对象构建
以在线招聘系统中的 Job 业务模型为例,定义如下几个简单属性。接下来以这个模型为例,介绍如何在代码中构建简单查询条件和复合查询条件。
public class Job {
private String title; // 职位名称
private Integer grade; // 职位等级: 1-20
private String status; // 职位状态: Open, Closed, Cancelled
private Integer salary; // 最低薪资,单位为 K
}
2.1 简单的 AND
条件查询
所有的查询操作方法,都支持 Lambda
表达式声明字段,如 Job::getTitle
、Job::getGrade
等,也支持字符串写法,如 "title"
、"grade"
等。
在专业代码中,建议使用 Lambda
表达式,以避免拼写错误和字段重构带来的影响。特殊情况下,可以使用字符串写法。
- 分别构建
filters1
和filters2
两个查询条件:
// WHERE title = 'PM'
Filters filters1 = new Filters().eq(Job::getTitle, "PM");
// WHERE grade > 6
Filters filters2 = new Filters().gt(Job::getGrade, 6);
使用字符串声明字段名的写法:
Filters filters1 = new Filters().eq("title", "PM");
Filters filters2 = new Filters().gt("grade", 6);
以下所有声明字段的操作方法,全部支持
Lambda
表达式写法和字符串写法,对应关系如下:
- Job::getTitle -> “title”
- Job::getGrade -> “grade”
- Job::getStatus -> “status”
- Job::getSalary -> “salary”
- 将
filters1
和filters2
用AND
逻辑合并,以下写法是等效的:
// .and(filters) 该 and 方法是一个非静态方法,仅接收一个 filters 参数
Filters filters3 = filters1.and(filters2);
// .and(filters1, filters2, Filters...) 该 and 方法是一个静态方法,至少两个 filters 参数
filters3 = Filters.and(filters1, filters2);
// Filter 默认是 `AND` 逻辑
filters3 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6);
filters3 = Filters.and().eq(Job::getTitle, "PM").gt(Job::getGrade, 6);
filters3
等价于以下SQL
语句:
WHERE title = 'PM' AND grade > 6
2.2 简单的 OR
条件查询
- 分别构建
filters4
和filters5
两个查询条件:
// WHERE status = 'Open'
Filters filters4 = new Filters().eq(Job::getStatus, "Open");
// WHERE salary < 30
Filters filters5 = new Filters().lt(Job::getSalary, 30);
- 将
filters4
和filters5
用OR
逻辑合并,以下写法是等效的:
// .or(filters) 该 or 方法是一个非静态方法,仅接收一个 filters 参数
Filters filters6 = filters4.or(filters5);
// .or(filters4, filters5, Filters...) 该 or 方法是一个静态方法,至少两个 filters 参数
filters6 = Filters.or(filters4, filters5);
filters6 = Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30);
filters6
等价于以下SQL
语句:
WHERE status = 'Open' OR salary < 30
2.3 复合查询条件:AND
逻辑合并
- 将
filters1
,filters2
,filters6
等多个查询对象,合并成一个AND
查询条件,以下写法是等效的:
// filters1 = new Filters().eq(Job::getTitle, "PM");
// filters2 = new Filters().gt(Job::getGrade, 6);
// filters6 = Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30);
// filters6 内部是一个 `OR` 逻辑
Filters filters7 = filters1.and(filters2).and(filters6);
filters7 = filters6.and(filters1).and(filters2);
filters7 = Filters.and(filters1, filters2, filters6);
filters7
等价于以下SQL
语句:
WHERE title = 'PM' AND grade > 6 AND (status = 'Open' OR salary < 30)
filters7
更多等效的写法,可以根据上下文变量情况选择性使用:
filters7 = filters1.and(filters2.and(filters6));
filters7 = filters1.and(Filters.and(filters2, filters6));
// 条件之间进行 `AND` 合并,子条件可以是 `OR` 查询条件
// filters6 = Filters.or(filters4, filters5);
filters7 = filters1.and(filters2)
.and(filters4.or(filters5));
filters7 = filters1.and(filters2)
.and(Filters.or(filters4, filters5));
filters7 = filters1.and(filters2)
.and(Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30));
filters7 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
.and(Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30));
// 先创建 `OR` 逻辑,再与其他条件进行 `AND` 合并
filters7 = filters4.or(filters5)
.and(filters1)
.and(filters2);
filters7 = Filters.or(filters4, filters5)
.and(filters1)
.and(filters2);
filters7 = Filters.or().or(filters4).or(filters5)
.and(filters1)
.and(filters2);
filters7 = Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30)
.and(filters1)
.and(filters2);
filters7 = Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30)
.and(new Filters().eq(Job::getTitle, "PM"))
.and(new Filters().gt(Job::getGrade, 6));
2.3 复合查询条件:OR
逻辑合并
- 将
filters3
,filters4
,filters5
等多个查询对象,合并成一个OR
查询条件,以下写法是等效的:
// filters3 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6);
// filters4 = new Filters().eq(Job::getStatus, "Open");
// filters5 = new Filters().lt(Job::getSalary, 30);
Filters filters8 = filters3.or(filters4).or(filters5);
filters8 = Filters.or(filters3, filters4, filters5);
filters8 = filters3.or(filters4).or(filters5);
filters8
等价于以下SQL
语句:
WHERE (title = 'PM' AND grade > 6) OR status = 'Open' OR salary < 30
filters8
更多等效的写法,可以根据上下文变量情况选择性使用:
filters8 = filters3.or(Filters.or(filters4, filters5));
// 条件之间进行 `OR` 合并,子条件可以是 `AND` 查询条件
// filters3 = Filters.and(filters1, filters2);
filters8 = Filters.and(filters1, filters2)
.or(filters4)
.or(filters5);
filters8 = Filters.and(filters1, filters2)
.or(filters4.or(filters5));
filters8 = filters4.or(filters5)
.or(Filters.and(filters1, filters2));
filters8 = filters4.or(filters5)
.or(filters1.and(filters2)));
// 先创建 `AND` 逻辑,再与其他条件进行 `OR` 合并
filters8 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
.or().eq(Job::getStatus, "Open")
.or().lt(Job::getSalary, 30);
filters8 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30);
filters8 = new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
.or(Filters.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30));
- Filters 查询条件构造顺序 Filters构造时遵循从左到右原则,如 “,解析逻辑如下:
new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
.or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30)
- (1)
new Filters().eq(Job::getTitle, "PM")
,等价于title = 'PM'
;- (2)
new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6)
,等价于title = 'PM' AND grade > 6
, 此时filters
对象为AND
逻辑;- (3)
new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6).or().eq(Job::getStatus, "Open")
, 等价于(title = 'PM' AND grade > 6) OR status = 'Open'
, 此时,filters
对象转变为OR
逻辑;- (4).
new Filters().eq(Job::getTitle, "PM").gt(Job::getGrade, 6).or().eq(Job::getStatus, "Open").lt(Job::getSalary, 30)
, 为继续增加一个OR
逻辑条件.lt(Job::getSalary, 30)
, 等价于(title = 'PM' AND grade > 6) OR status = 'Open' OR salary < 30
2.4 其它用法
- 多个 filters 对象合并
// 假设存在List<Filters> filtersList = Lists.newArrayList(filters1, filters2, filters3);
Filters filters = Filters.and(filtersList);