Skip to content

动态查询条件构建

动态条件主要使用Criteria类来实现。大多数情况下建议生成此类。

jdl中使用的语法是

md
filter \*

代码示例(Mybatis):

java
@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的情况下就可以不用这个了。

创建查询条件时会有如下条件生成,以引来生成一个简单的模糊查询功能。

java
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);
    }
}

前端的实现效果: keywords.png

1.2 useOr属性

默认值为False;

当useOr的值为True时,当前Criteria类下的属性使用or组装相应的sql条件。

当useOr的值为False时,当前Criteria类下的属性使用and组装相应的sql条件。

useOr=True时生成的sql语句:

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的方式赋值。最主要的目的是简化前端,毕竟有时不需要那样复杂的条件。

md
    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前端使用方式

最简单的方式

javascript
const params = {
  id: 3,
  login: 'admin',
};

复杂一点儿的方式:

javascript
const params = {
  id: 3,
  login: {
    not: 'user',
  },
};

更复杂一点儿的方式:

javascript
const params = {
  id: 3,
  login: {
    notContains: 'user',
  },
  useOr: true,
  and: {
    id: {
      notEquals: 2,
    },
    mobile: {
      containsLeft: '137',
    },
  },
};

另一种方式:

javascript
const params = {
  'id.equals': 3,
  'login.notContains': 'user',
  useOr: true,
  'and.id.notEquals': 2,
  'and.mobile.containsLeft': '137',
};

后端使用Get的方式接收参数,这样更灵活。

5. 前端SearchForm搜索表单

SearchForm搜索表单就是基上Criteria类的支持实现灵活的定制的。

javascript
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"等等方式。

前端搜索表单效果: search-form.png