MybatisPlus 查询条件封装,生成代码就可满足全表字段查询

248 阅读3分钟

项目背景

MybatisPlus 使得查询数据库变的简单,那么能否页面查询接口也变得这么简单?当然可以

目的

代码生成,就满足页面查询所有表字段的基本查询

实现

为了侵入小,使用工具类方式实现

1.基础功能

1.1主要代码在buildFieldWrapper (组装字段条件)

实现思路: 遍历实体,将字段对应值非空,加入eq(等于条件)

/**
 *组装字段条件
 */
private static <T> void buildFieldWrapper(T t, QueryWrapper<T> queryWrapper, Field[] declaredFields, TableAlias tableAlias) {
    for (Field field : declaredFields) {
        field.setAccessible(true);
        String fieldName = ReflectUtil.getFieldName(field);
        if("serialVersionUID".equals(fieldName)){
            //序列化id忽略
            continue;
        }
        QueryConditions queryConditions = field.getAnnotation(QueryConditions.class);
        //条件值
        Object fieldValue = ReflectUtil.getFieldValue(t, field);
        if(null == fieldValue || StrUtil.isBlank(fieldValue.toString())){
            continue;
        }

        //条件名称
        String dbFiledName  = getDbFieldName(tableAlias,field,queryConditions);

        if (queryConditions != null) {
            if (ConditionsType.EQ.equals(queryConditions.type())) {
                queryWrapper.eq(dbFiledName, fieldValue);
            }
            if (ConditionsType.LIKE.equals(queryConditions.type())) {
                queryWrapper.like(dbFiledName, fieldValue);
            }
        }else {
            //默认都是等于条件
            queryWrapper.eq(dbFiledName, fieldValue);
        }
    }
}

1.2 使用

将参数类,传入工具方法

public IPage<JobPageResVo> queryPage(JobPageQueryVo pageQueryVo, PageVo page) {
    Page convert = Convert.convert(Page.class, page);
    return this.baseMapper.queryPage(convert, QueryWrapperUtils.toQueryWrapper(pageQueryVo));
}

2.扩展功能

2.1扩展其他条件

注解

只是等于满足不了需求,使用注释方式实现

package com.g_link.phm.common.annocation.QueryHandle;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 查询条件
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryConditions {

    /**
     * 条件
     */
    ConditionsType type() default ConditionsType.EQ;

    /**
     *自定义查询字段,
     * 如多表关联需要配置【表名.字段名】(b.name)
     */
    String queryFiled() default "";
}

枚举类,举出需要的条件

package com.g_link.phm.common.annocation.QueryHandle;

public enum ConditionsType {
    /**
     * 等于
     */
    EQ,
    /**
     * 模糊查询
     */
    LIKE
}

使用范例

@QueryConditions(type = ConditionsType.LIKE)

public class BookEntity implements Serializable {

    private static final long serialVersionUID=1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 作业名称
     */
    @QueryConditions(type = ConditionsType.LIKE)
    private String name;
}

2.2 快展排序

注解

package com.g_link.phm.common.annocation.QueryHandle;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface OrderBy {
    String desc() default "create_at";

    String asc() default "";
}

使用范例

@OrderBy(desc = "b.create_at")
@GroupBy("b.id")
@Data
public class BookPageQueryVo {

2.3 扩展分组group by

注解

package com.g_link.phm.common.annocation.QueryHandle;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GroupBy {
    String value();
}

使用范例

@OrderBy(desc = "j.create_at")
@GroupBy("j.id")
@Data
public class JobPageQueryVo {

2.4 扩展表别名

如果使用了关联查询,表一搬会起别名

注解

/**
 * 表,别名,
 * 用于关联查询起了别名查询条件使用
 * 如:别名 t
 * select t.* from table t
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableAlias {
    String value();
}

使用范例

@TableAlias("b")
public class BookEntity implements Serializable {

3.完整工具类代码

package com.g_link.phm.common.util;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.g_link.phm.common.annocation.QueryHandle.*;

import java.lang.reflect.Field;

/**
 * 根据【实体注解】,组装查询条件
 */
public class QueryWrapperUtils {

    public static <T> QueryWrapper toQueryWrapper(T t) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        //组装排序
        buildOrderBy(t, queryWrapper);
        //组装分组
        buildGroupBy(t, queryWrapper);
        //组装查询条件
        buildQueryWrapper(t, queryWrapper);
        return queryWrapper;
    }

    /**
     * 组装查询条件
     * @param t 实体
     * @param queryWrapper 返回查询条件对象
     */
    private static <T> void buildQueryWrapper(T t, QueryWrapper<T> queryWrapper) {
        TableAlias tableAlias = t.getClass().getAnnotation(TableAlias.class);
        //组装字段条件
        buildFieldWrapper(t, queryWrapper, t.getClass().getDeclaredFields(), tableAlias);

        //应付扩展查询vo,查询实体中字段情况
        Class<?> superclass = t.getClass().getSuperclass();
        tableAlias = superclass.getAnnotation(TableAlias.class);
        if(tableAlias != null) {
            //组装字段条件
            buildFieldWrapper(t, queryWrapper, superclass.getDeclaredFields(), tableAlias);
        }
    }

    /**
     *组装字段条件
     */
    private static <T> void buildFieldWrapper(T t, QueryWrapper<T> queryWrapper, Field[] declaredFields, TableAlias tableAlias) {
        for (Field field : declaredFields) {
            field.setAccessible(true);
            String fieldName = ReflectUtil.getFieldName(field);
            if("serialVersionUID".equals(fieldName)){
                //序列化id忽略
                continue;
            }
            QueryConditions queryConditions = field.getAnnotation(QueryConditions.class);
            //条件值
            Object fieldValue = ReflectUtil.getFieldValue(t, field);
            if(null == fieldValue || StrUtil.isBlank(fieldValue.toString())){
                continue;
            }

            //条件名称
            String dbFiledName  = getDbFieldName(tableAlias,field,queryConditions);

            if (queryConditions != null) {
                if (ConditionsType.EQ.equals(queryConditions.type())) {
                    queryWrapper.eq(dbFiledName, fieldValue);
                }
                if (ConditionsType.LIKE.equals(queryConditions.type())) {
                    queryWrapper.like(dbFiledName, fieldValue);
                }
            }else {
                //默认都是等于条件
                queryWrapper.eq(dbFiledName, fieldValue);
            }
        }
    }

    /**
     * 组装分组
     * @param t 实体
     * @param queryWrapper 返回查询条件对象
     */
    private static <T> void buildGroupBy(T t, QueryWrapper<T> queryWrapper) {
        GroupBy groupBy = t.getClass().getAnnotation(GroupBy.class);
        if(groupBy != null && StrUtil.isNotBlank(groupBy.value())){
            queryWrapper.groupBy(groupBy.value());
        }
    }

    /**
     * 组装排序
     * @param t 实体
     * @param queryWrapper 返回查询条件对象
     */
    private static <T> void buildOrderBy(T t, QueryWrapper<T> queryWrapper) {
        OrderBy order = t.getClass().getAnnotation(OrderBy.class);
        if(order != null) {
            if(StrUtil.isNotBlank(order.desc())){
                queryWrapper.orderByDesc(order.desc());
            }
            if(StrUtil.isNotBlank(order.asc())){
                queryWrapper.orderByAsc(order.asc());
            }
        }
    }

    /**
     * 获取数据库字段名称
     * 1.是否有自定义【数据库字段名】,有则直接使用
     * 2.没有则,将实体字段转换为【数据库字段】
     *   2.1如果有表明,则加表明前缀,组装为tableAlias.filed;应对多变关联查询
     * @param tableAlias 关联查询起得表别名
     * @param field 实体字段名称
     * @param queryConditions 查询条件,包含
     */
    private static String getDbFieldName(TableAlias tableAlias,Field field,QueryConditions queryConditions) {
        String dbFiledName = "";
        if(queryConditions != null && StrUtil.isNotBlank(queryConditions.queryFiled())){
            dbFiledName = queryConditions.queryFiled();
        }else {
            String fieldName = ReflectUtil.getFieldName(field);
            StringBuilder dbFiledNameBuilder = new StringBuilder(fieldName.charAt(0) + "");
            for (int i = 1; i < fieldName.length(); i++) {
                char c = fieldName.charAt(i);
                if(Character.isUpperCase(c)){
                    dbFiledNameBuilder.append("_").append(Character.toLowerCase(c));
                }else {
                    dbFiledNameBuilder.append(c);
                }
            }
            dbFiledName = dbFiledNameBuilder.toString();
            if(tableAlias != null && StrUtil.isNotBlank(tableAlias.value())){
                dbFiledName = tableAlias.value()+"."+ dbFiledNameBuilder;
            }
        }

        return dbFiledName;
    }
}