首页 > 其他分享 >MyBatisPlus查询对象转QueryWrapper工具类

MyBatisPlus查询对象转QueryWrapper工具类

时间:2022-10-01 12:31:29浏览次数:45  
标签:QueryWrapper MyBatisPlus String queryWrapper memberQuery 查询 private logic public

技术背景

在使用MyBatisPlus技术实际项目中,尤其是后台管理系统之类的项目中,经常会出现大量的需要将查询对象转换成QueryWrapper的应用场景,这时候就需要编写出现大量的转换代码,比如:

待转换的查询实体类

@Getter
@Setter
@ToString(callSuper = true)
public class MemberQuery  extends BaseQuery {

    /**
     * 昵称
     */
    private String nickname;

    /**
     * 性别:1女 2男 3未知
     */
    private Integer gender;

    /**
     * 生日:下限
     */
    private LocalDate start;
    /**
     * 生日:上限
     */
    private LocalDate end;

    /**
     * 电话
     */
    private String tel;

    /**
     * 外键:角色编号
     */
    private Long roleId;

    /**
     * 状态:1未激活 2激活
     */
    private Integer state;

    @Builder
    public MemberQuery(Integer pageNum, Integer pageSize, String nickname, Integer gender, LocalDate start, LocalDate end, String tel, Long roleId, Integer state) {
        super(pageNum, pageSize);
        this.nickname = nickname;
        this.gender = gender;
        this.start = start;
        this.end = end;
        this.tel = tel;
        this.roleId = roleId;
        this.state = state;
    }
}

上面查询类引用的BaseQuery封装了分页信息,具体代码如下:

@Setter
@ToString
@AllArgsConstructor
public class BaseQuery {
    /**
     * 页码
     */
    private Integer pageNum;
    /**
     * 页面大小
     */
    private Integer pageSize;

    public Integer getPageNum() {
        return pageNum == null ? 1 : pageNum;
    }

    public Integer getPageSize() {
        return pageSize == null ? GlobalConst.PAGE_SIZE : pageSize;
    }
}

在Controller中进行转换

@PostMapping("/list")
public ResultBean list(@RequestBody MemberQuery memberQuery) {
    IPage<Member> page = new Page<>(memberQuery.getPageNum(), memberQuery.getPageSize());

    LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();

    if (memberQuery.getNickname() != null) {
        queryWrapper.like(Member::getNickname, memberQuery.getNickname());
    }
    if (memberQuery.getTel() != null) {
        queryWrapper.like(Member::getTel, memberQuery.getTel());
    }
    if (memberQuery.getGender() != null) {
        queryWrapper.eq(Member::getGender, memberQuery.getGender());
    }
    if (memberQuery.getRoleId() != null) {
        queryWrapper.eq(Member::getRoleId, memberQuery.getRoleId());
    }
    if (memberQuery.getState() != null) {
        queryWrapper.eq(Member::getState, memberQuery.getState());
    }
    if (memberQuery.getStart() != null) {
        queryWrapper.ge(Member::getBirth,memberQuery.getStart());
    }
    if(memberQuery.getEnd() != null){
        queryWrapper.le(Member::getBirth,memberQuery.getEnd());
    }

    memberService.page(page, queryWrapper);

    PageBean<Member> pageBean = PageBean.init(page);

    return ResultBeanUtil.success().buildData("pageBean",pageBean);
}

上面大量的转换代码,不仅写起来烦琐,而且也不优雅。此时可以采用注解+反射技术编写一个工具类:将Query对象转换成Wrapper,具体代码如下:

优化方案

表示关系运算的接口

public interface Logic {
    String and = "AND";
    String or = "OR";
}

表示逻辑运算的枚举

  • Between
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Between {
    String logic() default Logic.and;
}
  • EQ
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EQ {
    String logic() default Logic.and;

    String value() default "";
}
  • IN
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IN {
    String logic() default Logic.and;

    String value() default "";
}
  • Like
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Like {
    String logic() default "AND";

    String value() default "";
}
  • NE
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NE {
    String logic() default Logic.and;

    String value() default "";
}

封装区间的Bean

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class RangeBean<T> {
    /**
     * 下限
     */
    private T start;
    /**
     * 上限
     */
    private T end;
}

具体转换的工具类

public class QueryWrapperUtil<T> {

    /**
     * 将查询对象转换成MyBatisPlus中的QueryWrapper
     * @param query
     * @param <T>
     * @return
     */
    public static <T> QueryWrapper<T> build(Object query) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();

        //获取Query类中都有哪些属性
        final Field[] fields = query.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            java.lang.Object fieldValue = null;
            try {
                fieldValue = field.get(query);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (fieldValue != null) {
                //获取Query类属性上的注解
                final Annotation[] annotations = field.getAnnotations();
                for (Annotation annotation : annotations) {
                    //获取Query类属性的名称
                    final String fieldName = field.getName();
                    //获取Query类对应的表字段名
                    final String columnName = StringUtil.hump2underscore(fieldName);

                    //获取Query类属性上的注解类型的字节码
                    final Class<? extends Annotation> annotationType = annotation.annotationType();
                    if (EQ.class == annotationType) {
                        EQ eq = (EQ) annotation;
                        fun(eq.logic(), queryWrapper);
                        queryWrapper.eq(columnName, fieldValue);
                    } else if (Like.class == annotationType) {
                        Like like = (Like) annotation;
                        fun(like.logic(), queryWrapper);
                        queryWrapper.like(columnName, fieldValue);
                    } else if (IN.class == annotationType) {
                        IN in = (IN) annotation;
                        fun(in.logic(), queryWrapper);
                        queryWrapper.in(columnName, fieldValue);
                    } else if (NE.class == annotationType) {
                        NE ne = (NE) annotation;
                        fun(ne.logic(), queryWrapper);
                        queryWrapper.ne(columnName, fieldValue);
                    } else if (Between.class == annotationType) {
                        Between between = (Between) annotation;
                        fun(between.logic(), queryWrapper);
                        RangeBean rangeBean = (RangeBean) fieldValue;
                        queryWrapper.between(columnName, rangeBean.getStart(), rangeBean.getEnd());
                    }
                }
            }
        }
        return queryWrapper;
    }

    /**
     * 添加or关系
     * @param logic
     * @param queryWrapper
     * @param <T>
     */
    private static <T> void fun(String logic, QueryWrapper<T> queryWrapper) {
        if ("or".equalsIgnoreCase(logic)) {
            queryWrapper.or();
        }
    }

}

优化方案:工具类应用

@PostMapping("/list")
public ResultBean list(@RequestBody MemberQuery memberQuery) {
    IPage<Member> page = new Page<>(memberQuery.getPageNum(), memberQuery.getPageSize());
    QueryWrapper<Member> queryWrapper = QueryWrapperUtil.build(memberQuery);
    memberService.page(page, queryWrapper);
    PageBean<Member> pageBean = PageBean.init(page);
    return ResultBeanUtil.success().addData("pageBean",pageBean);
}

标签:QueryWrapper,MyBatisPlus,String,queryWrapper,memberQuery,查询,private,logic,public
From: https://blog.51cto.com/lianghecai/5728183

相关文章

  • EF Core 分页查询
    提示:分页查询时,尽量显式地指定排序规则[HttpGet("{pageIndex:int}/{pageSize:int}")]publicasyncTask<ActionResult<IEnumerable<Book>>>GetPage(intpageIn......
  • EF Core 查询性能优化
    一、IEnumerable和IQueryable的区别1.IEnumerable1.1是立即Sql查询执行,除了生成首次的Where条件之外,之后的查询条件都是在内存中进行,当数据量很大时,性能就会有问......
  • 学习笔记——Django项目中关联查询以及关联查询的筛选
    2022-10-01关联查询:在Django项目中使用ORM模式设置表后,进行关联查询,即两个表直接有联系的查询。方式:可以通过主表查询从表,也可以通过从表查询主表。---------......
  • 三角函数计算方法及快速查询表,做数控真是太有用了
    今天小编给大家整理了关于函数的计算方法,这应该对从事数控行业的你有所帮助,不会的赶紧学学吧。三角函数的关系(正弦)Sinθ=对边A/斜边C(余弦)Cosθ=邻边B/斜边C(......
  • 源码学习之MyBatis的底层查询原理
    导读本文通过MyBatis一个低版本的bug(3.4.5之前的版本)入手,分析MyBatis的一次完整的查询流程,从配置文件的解析到一个查询的完整执行过程详细解读MyBatis的一次查询流程,通过本......
  • 多条件查询 (数据库字段数据逗号拼接)
    问题描述:源代码只有单一条件,即只需输入一个人名进行查找并返回结果即可,因此,只需要动态Sql同时使用like关键字,使用concat函数将%与动态数据拼接即可实现模糊查找功能。仔细......
  • 【学习笔记】联表查询和自连接
    联表查询和自连接 七种join理论 想要在多个表中查询数据的思路:分析需求,即想要查询哪些字段,以及这些字段来自哪些表确定使用哪种连接,即七种join中的哪一种......
  • MYSQL 列值为JSON串匹配条件查询
    这里需定位到你要查询的字段再json中的位置。比如我需要我的列值JSON格式如下:我需要匹配Tin(123456,223432)可以像下面这样写SELECTREPLACE(JSON_EXTRACT(wms_r......
  • 学习笔记——Django项目的删除数据、查询数据(filter、get、exclude)
    2022-09-30删除数据:方式一:打开pycharm,进入虚拟环境,进入shell环境(pythonmanage.pyshell)。删除数据,接上面的笔记——“学习笔记——Django项目的新增数据、修改数据”......
  • https证书过期时间查询脚本
    #!/bin/bashfile=$1expire=$2functionstart(){rm-rf./info.log./list.txt./res.txt./end.txt./res_${file}}functionget_domain(){cat$file|......