模糊查询大致思路是先遍历实体类,然后实体类如果有值,则获取它的 TableField 注解,获取字段名,然后拼接 wrapper 。
时间查询的大体思路和上面差不多,前端传来 xxxStart 和 xxxxEnd, 首先保存到实体类中,然后再做字符拼接。
想起写这个的原因是因为基本每个前端 Table 都需要类似的查询,本来是写在 XML 文件里,但是每改一次字段都会联动着更改 XML ,太过繁琐,增加出错几率。 所以写了这么一个工具类来通过实体类动态拼接模糊查询。
//拼接函数 /** * 通过实体类生成模糊搜索和日期区间查询的 wrapper * @param cls 类名 * @param entity 实体类 * @param orderByField 排序字段 * @param orderByAsc 是否升序 * @return QueryWrapper * @param <T&g; 实体类 */ public <T> QueryWrapper<T> generateFuzzySearchAndBetweenDateWrapper(Class<T> cls, T entity, String orderByField, Boolean orderByAsc) { QueryWrapper<T> wrapper = new QueryWrapper<>(); //先检查是否排序 if (!DataUtil.isEmpty(orderByField)) { wrapper.orderBy(true, orderByAsc, StringFormat.camelToUnderscore(orderByField)); } //再检查实体类是否为空 if (DataUtil.isEmpty(entity)) { return wrapper; } try { //遍历实体类的所有字段. getAllFields 方法获取不止当前类的字段, 还包括父类的字段 for (Field field: DataUtil.getAllFields(cls)) { //如果是 final, static, transient 修饰的字段, 则跳过. 一般用来排除 private static final long serialVersiOnUID= 1L; 序列化 id if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { continue; } //获取字段的 get 方法 Method getFunc = cls.getMethod("get" + StringFormat.capitalize(field.getName())); Object value = getFunc.invoke(entity); //如果字段有 TableField 注解, 并且值不为空 if (field.isAnnotationPresent(TableField.class) && !DataUtil.isEmpty(value)) { //如果 TableField 注解的 exist 属性为 true, 则使用注解的 value 作为字段名 if (field.getAnnotation(TableField.class).exist()) { String column = field.getAnnotation(TableField.class).value(); wrapper.like(column, value); } else { //如果 TableField 注解的 exist 属性为 false, 证明可能是一个时间区域查询 String name = field.getName(); if (name.endsWith("Start")) { String column = name.substring(0, name.length() - 5); wrapper.ge(StringFormat.camelToUnderscore(column), value); } else if (name.endsWith("End")) { String column = name.substring(0, name.length() - 3); wrapper.le(StringFormat.camelToUnderscore(column), value); } } } } } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new RuntimeException(e); } return wrapper; } //controller @GetMapping("select/page") public IPage<Company> selectPage(@RequestBody(required = false) Company company, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false)String orderByField, @RequestParam(defaultValue = "true")Boolean orderByAsc) { QueryWrapper<Company> companyQueryWrapper = generateFuzzySearchAndBetweenDateWrapper(Company.class, company, orderByField,orderByAsc); Page<Company> companyPage = new Page<>(); companyPage.setCurrent(current); companyPage.setSize(size); IPage<Company> companyIPage = companyService.page(companyPage, companyQueryWrapper); return companyIPage; } 已知的问题:
1.Get 请求携带请求体,功能是可以实现,但似乎有些不合规矩,隐隐约约记得当时学 J2EE 的时候有讲过不要在 Get 请求携带请求体
2.每个时间字段都需要增加两个虚拟属性,用于接受前端发来的时间范围数据
@TableField("expire_date") @ApiModelProperty(value = "到期时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date expireDate; @TableField(exist = false) private String expireDateStart; @TableField(exist = false) private String expireDateEnd; 3.想实现数据字典的功能,但是感觉有点复杂, 首先需要调用其他 Service 来查询数据表,然后实体类还需要多加一个虚拟字段,用于存储数据字典对应的值。例如:
@TableField("industry_type") @ApiModelProperty(value = "企业类型") private Integer industryType; @TableField(exist = false) private String industryTypeValue; 