动态查询条件构建
动态条件主要使用Criteria类来实现。大多数情况下建议生成此类。
jdl中使用的语法是
filter \*
代码示例(Mybatis):
@ParameterObject
@SuppressWarnings("common-java:DuplicatedBlocks")
public class UserCriteria implements Serializable, Criteria {
@BindQuery(ignore = true)
private String jhiCommonSearchKeywords;
@BindQuery(ignore = true)
private Boolean useOr;
@BindQuery(ignore = true)
private UserCriteria and;
@BindQuery(ignore = true)
private UserCriteria or;
@BindQuery(column = "self.id")
private LongFilter id;
@BindQuery(column = "self.login")
private StringFilter login;
@BindQuery(column = "self.department_id")
private LongFilter departmentId;
@BindQuery(entity = Department.class, column = "name", condition = "this.department_id=id")
private StringFilter departmentName;
@BindQuery(column = "self.position_id")
private LongFilter positionId;
@BindQuery(entity = Position.class, column = "name", condition = "this.position_id=id")
private StringFilter positionName;
}
1. 示例说明
这是一个User实体的Criteria类,动态查询条件的构建一般会使用到。包括分页列表接口、count统计接口、统计汇总接口等。
1.1 jhiCommonSearchKeywords属性
这是一个与实体和数据库字段无关的属性,用来接收前端搜索关键字,然后转换到相应字段上进行模糊查询,在使用Elasticsearch的情况下就可以不用这个了。
创建查询条件时会有如下条件生成,以引来生成一个简单的模糊查询功能。
public QueryWrapper<User> createQueryWrapper(UserCriteria criteria) {
if (StringUtils.isNotEmpty(criteria.getJhiCommonSearchKeywords())) {
String keywords = criteria.getJhiCommonSearchKeywords();
criteria.setJhiCommonSearchKeywords(null);
UserCriteria keywordsCriteria = new UserCriteria();
keywordsCriteria.setUseOr(true);
if (StringUtils.isNumeric(keywords)) {
keywordsCriteria.id().setEquals(Long.valueOf(keywords));
keywordsCriteria.createdBy().setEquals(Long.valueOf(keywords));
keywordsCriteria.lastModifiedBy().setEquals(Long.valueOf(keywords));
}
keywordsCriteria.login().setContains(keywords);
keywordsCriteria.firstName().setContains(keywords);
keywordsCriteria.lastName().setContains(keywords);
keywordsCriteria.email().setContains(keywords);
keywordsCriteria.mobile().setContains(keywords);
keywordsCriteria.langKey().setContains(keywords);
keywordsCriteria.imageUrl().setContains(keywords);
UserCriteria tempCriteria = criteria;
while (tempCriteria.getAnd() != null) {
tempCriteria = tempCriteria.getAnd();
}
tempCriteria.setAnd(keywordsCriteria);
}
}
前端的实现效果:
1.2 useOr属性
默认值为False;
当useOr的值为True
时,当前Criteria类下的属性使用or
组装相应的sql
条件。
当useOr的值为False
时,当前Criteria类下的属性使用and
组装相应的sql
条件。
useOr=True时生成的sql语句:
SELECT DISTINCT self.*
FROM jhi_authority self
LEFT OUTER JOIN jhi_authority r1 ON r1.id = r1.parent_id
LEFT OUTER JOIN rel_jhi_authority__view_permissions r2m ON self.id = r2m.jhi_authority_id
LEFT OUTER JOIN view_permission r2 ON r2m.view_permissions_id = r2.id
LEFT OUTER JOIN rel_jhi_authority__api_permissions r3m ON self.id = r3m.jhi_authority_id
LEFT OUTER JOIN api_permission r3 ON r3m.api_permissions_id = r3.id
LEFT OUTER JOIN jhi_authority r4 ON self.parent_id = r4.id
WHERE
((self.parent_id IS NULL)
AND (((self.name LIKE ?)) OR ((self.code LIKE ?)) OR ((self.info LIKE ?)))) LIMIT ?
1.3 and属性
通过and属性可以使用and
连接符号将当前Criteria类的条件与and属性所指向的Criteria条件连接起来。
1.4 or属性
通过and属性可以使用or
连接符号将当前Criteria类的条件与or属性所指向的Criteria条件连接起来。
1.5 构建复杂条件
通过控制useOr/and/or等3个属性及一定程度的嵌套,就能实现比较复杂的查询条件。
1.6 self.*属性
以self.
开始的@BindQuery注解属性,是关联实体相关数据库字段的。
1.7 @BindQuery(entity = *.class)属性
这是通过其他关联实体进行查询的,使用LEFT OUT JOIN方式。
示例中departmentName属性可以通过部门名称查找和部门关联的用户。
@BindQuery注解由Diboot-core框架提供。支持复杂条件的关联设置。
2. Criteria类使用场景
2.1 分页列表的api接口
2.2 统计汇总的api接口
2.3 service类中需要复合查询时
3. XxxxFilter类说明
这是一系列由JHipster提供的接口,可以根据属性设置不同的条件。
BegCode主要的工作就是将其翻译为Mybatis-Plus可识别的QueryWrapper。
BegCode对其做了一个增强,就是支持默认赋值: 原始方式:id.equals = 1,新的方式可直接支持一个默认值id=1的方式赋值。最主要的目的是简化前端,毕竟有时不需要那样复杂的条件。
id.setEquals(1); 表示id=1的条件
以下是更多的方式。
fieldName.equals=42
fieldName.notEquals=42
fieldName.specified=true
fieldName.specified=false
fieldName.in=43,42
fieldName.notIn=43,42
fieldName.greaterThan=41
fieldName.lessThan=44
fieldName.greaterThanOrEqual=42
fieldName.lessThanOrEqual=44
4. Criteria前端使用方式
最简单的方式
const params = {
id: 3,
login: 'admin',
};
复杂一点儿的方式:
const params = {
id: 3,
login: {
not: 'user',
},
};
更复杂一点儿的方式:
const params = {
id: 3,
login: {
notContains: 'user',
},
useOr: true,
and: {
id: {
notEquals: 2,
},
mobile: {
containsLeft: '137',
},
},
};
另一种方式:
const params = {
'id.equals': 3,
'login.notContains': 'user',
useOr: true,
'and.id.notEquals': 2,
'and.mobile.containsLeft': '137',
};
后端使用Get的方式接收参数,这样更灵活。
5. 前端SearchForm搜索表单
SearchForm搜索表单就是基上Criteria类的支持实现灵活的定制的。
const searchForm = () => {
return [
{
title: '用户ID',
field: 'id',
componentType: 'Text',
value: '',
type: 'Long',
operator: '',
span: 8,
componentProps: {},
},
{
title: '账户名',
field: 'login',
componentType: 'Text',
value: '',
type: 'String',
operator: '',
span: 8,
componentProps: {},
},
{
title: '名字',
field: 'firstName',
componentType: 'Text',
value: '',
type: 'String',
operator: '',
span: 8,
componentProps: {},
},
{
title: '姓氏',
field: 'lastName',
componentType: 'Text',
value: '',
type: 'String',
operator: '',
span: 8,
componentProps: {},
},
{
title: '电子邮箱',
field: 'email',
componentType: 'Text',
value: '',
type: 'String',
operator: '',
span: 8,
componentProps: {},
},
{
title: '手机号码',
field: 'mobile',
componentType: 'Text',
value: '',
type: 'String',
operator: '',
span: 8,
componentProps: {},
},
];
};
其中operator: '',
,可以更换不同的操作符,如"equals","notEquals","in","notIn"等等方式。
前端搜索表单效果: