Java , 写了一个生成模糊查询和时间区间查询 wrapper 的函数,有什么优化建议或是隐藏的坑吗?

16次阅读

共计 3021 个字符,预计需要花费 8 分钟才能阅读完成。

模糊查询大致思路是先遍历实体类,然后实体类如果有值,则获取它的 TableField 注解,获取字段名,然后拼接 wrapper。
时间查询的大体思路和上面差不多,前端传来 xxxStart 和 xxxxEnd, 首先保存到实体类中,然后再做字符拼接。
想起写这个的原因是因为基本每个前端 Table 都需要类似的查询,本来是写在 XML 文件里,但是每改一次字段都会联动着更改 XML,太过繁琐,增加出错几率。所以写了这么一个工具类来通过实体类动态拼接模糊查询。

// 拼接函数
/**
     * 通过实体类生成模糊搜索和日期区间查询的 wrapper
     * @param cls   类名
     * @param entity    实体类
     * @param orderByField  排序字段
     * @param orderByAsc    是否升序
     * @return  QueryWrapper
     * @param    实体类
     */
    public  QueryWrapper generateFuzzySearchAndBetweenDateWrapper(Class cls, T entity, String orderByField, Boolean orderByAsc) {QueryWrapper 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 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 companyQueryWrapper = generateFuzzySearchAndBetweenDateWrapper(Company.class, company, orderByField,orderByAsc);
        Page companyPage = new Page<>();
        companyPage.setCurrent(current);
        companyPage.setSize(size);
        IPage 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;
正文完
 0