MybatisPlus使用queryWrapper如何实现复杂查询

 更新时间:2022年01月11日 10:04:36   作者:程序小白__向阳  
这篇文章主要介绍了MybatisPlus使用queryWrapper如何实现复杂查询,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。

使用queryWrapper实现复杂查询

//    mp实现负责查询操作
    @Test
    public void testSelectQuery(){
        //1,创建QueryWrapper对象
        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        2,通过QueryWrapper设置条件
//        ge大于等于  gt大于  le小于等于 lt   eq等于  ne不等于  between  like模糊查询
//        orderByDesc   last拼接
//        查询age>=30的记录 第一个参数 字段的名字,第二个参数设置值
        wrapper.ge("age",30);
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
//        eq
        wrapper.eq("name","Tian");
        List<User> users1 = userMapper.selectList(wrapper);
        System.out.println(users1);
        wrapper.ne("name","Tian");
        List<User> users2 = userMapper.selectList(wrapper);
        System.out.println(users2);
//        between
//        查询年龄20-30
        wrapper.between("age",20,30);
        List<User> users3 = userMapper.selectList(wrapper);
        System.out.println(users3);
//        like
        wrapper.like("Tian","T");
        List<User> users4 = userMapper.selectList(wrapper);
        System.out.println(users4);
//        orderByDesc
        wrapper.orderByAsc("age");
        List<User> users5 = userMapper.selectList(wrapper);
        System.out.println(users5);
//        last 拼接
        wrapper.last("limit 1");
        List<User> users6 = userMapper.selectList(wrapper);
        System.out.println(users6);
//        指定要查询的列
        QueryWrapper<User> select = wrapper.select("id", "name");
    }

自定义的queryWrapper实现查询

想要用QueryMapper,而不用xml,所以为了实现若依那样的,自己重写了QueryMapper

原有的mybatis的查询方法,例如查询一个用户,那么查询方法就传一个用户,然后在mapper.xml中对用户的各项属性进行判断,然后再拼接相应的sql语句,就可以一次性实现查询。虽然有mybatisX代码生成器,或者自己写代码生成器,但是多个表的话感觉还是有点不好用。所以,自己使用反射写了一个QueryWrapper的myAllEq方法,可以实现传入一个实体类,直接实现全部属性查询

声明提要

package com.maoyan.quickdevelop.common.core.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.maoyan.quickdevelop.common.core.domain.dqabstract.DqStatusDispose;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Date;
/**
 * @author 猫颜
 * @date 2021/5/27 21:28
 * 用户实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "dq_user")
public class DqUser extends DqStatusDispose implements Serializable {
    private static final long serialVersionUID = 1L;
    /** 用户ID */
    /**
     * 主键使用TableId注解,否则MybatisPlus默认使用id来查询
     */
    @TableId(value = "user_id")
    private Long userId;
    /** 用户账号 */
    @TableField(value = "user_name")
    private String userName;
    /** 用户昵称 */
    @TableField(value = "nick_name")
    private String nickName;
    /** 用户邮箱 */
    @Email(message = "邮箱格式不正确")
    @TableField(value = "email")
    private String email;
    /** 手机号码 */
    @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
    @TableField(value = "phone_number")
    private String phonenumber;
    /** 用户性别 0=男,1=女,2=未知*/
    @TableField(value = "sex")
    private String sex;
    /** 用户头像 */
    @TableField(value = "avatar")
    private String avatar;
    /** 密码 */
    @TableField(value = "password")
    private String password;
    /** 帐号状态(0正常 1停用) */
    @TableField(value = "status")
    private String status;
    /** 删除标志(0代表存在 1代表删除,暂时没打算用) */
    @TableField(value = "delFlag")
    private String delFlag;
    /** 最后登录IP */
    @TableField(value = "loginIp")
    private String loginIp;
    /** 最后登录时间 */
    @TableField(value = "loginDate")
    private Date loginDate;
    /** 用户角色ID */
    @TableField(value = "role")
    private String role;
    /** 个性签名 **/
    @TableField(value = "signature")
    private String signature;
    /** 创建时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** 更新时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}
  • 我的用户实体类中,使用lombak,里面有serialVersionUID。
  • 使用的是注解来映射数据库字段名

核心代码

    /**
     * TODO 自定义遍历查询方法
     *
     * @param object
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>
     * @author 猫颜
     * @date 下午9:20
     */
    public QueryWrapper<T> myAllEq(T object) throws IllegalAccessException,
            NoSuchMethodException,
            InvocationTargetException {
        String getMethodName = "";
        Field field = null;
        Class<?> aClass = object.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
//        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        //第一个为serialVersionUID(舍去) i为1 绕过
        //获取object的所有字段
        for (int i = 1; i < declaredFields.length; i++) {
            field = declaredFields[i];
            //类中的成员变量为private,故必须进行此操
            field.setAccessible(true);
//            不能直接获取到值,可以通过构造get方法,或者调用类的get方法来获取值
//            通过StringUtils的containsIgnoreCase方法来获取方法名称
//            通过上面那种方法,有循环嵌套,性能需要优化
//            所以采取拼接get方法名
/**
 *
 * @author 猫颜
 * @date         //获取属性名称
 *         for (Field field:
 *              declaredFields) {
 *             System.out.println(field.getName());
 *             methodNameFirst = field.getName().substring(0,1).toUpperCase();
 *             methodName = field.getName();
 *             methodName = "get"+methodNameFirst+methodName.substring(1);
 *             System.out.println("方法名称为:"+methodName);
 *
 * //            优化
 *             System.out.println("优化:"+"get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1));
 *         } 下午5:18
 * @param object
 * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>
 */
//获取get方法名称
            getMethodName = "get" + declaredFields[i].getName().substring(0, 1).toUpperCase() + declaredFields[i].getName().substring(1);
            System.out.println(getMethodName);
//            执行get方法获取属性值
            //执行方法
            Method method = aClass.getMethod(getMethodName, null);
            Object getValue = method.invoke(object, null);
            //System.out.println("输出为:"+invoke);
//            System.out.println("优化:"+"get"+declaredFields[i].getName().substring(0,1).toUpperCase()+declaredFields[i].getName().substring(1));
//            如果值不为空,则添加到eq中
            if (getValue != null) {
                //映射关系
//                return super.eq(,field.get(object));
                //获取其注解的值
//                后面可以采用查询方法注释来解决,不同的查询所需的问题
                System.out.println("表的值:" + field.getAnnotation(TableField.class).value());
                System.out.println("get获取值:" + getValue.toString());
                MyQueryWrapper.this.eq(field.getAnnotation(TableField.class).value(), getValue.toString());
            }
        }
        return MyQueryWrapper.this;
    }

可以使用

        //获取所有的方法名称
        //但是顺序是与类中的一样,所以可以构建get方法
        //属性名称第一个大写,然后加上get就是,get方法名称
        Method[] methods = aClass.getMethods();
        for (Method method:
             methods) {
            System.out.println(method.getName());
            if (StringUtils.containsIgnoreCase(method.getName(),"get")&&
                    StringUtils.containsIgnoreCase(method.getName(),"username")){
                System.out.println("值为:"+method.getName());
            }
        }

StringUtils.containsIgnoreCase方法来获取get方法,但是会造成循环嵌套,对性能有一定的影响。

所以,我采用拼接get方法名称的方法,减少无用循环带来的影响。

  • 根据上面的要点提示,for是从1开始,因为第一个是serialVersionUID,所以为了跳过他。从1开始
  • 对于xml中,可以使用like等查询,我这个是适用于=查询,所以后续会通过在用户类的属性上加上自定义注解,来判断这个字段所用的查询方式,对于一个字段,有些地方想用=来查,有些地方想用like来查,那可以设定注解有优先等级来解决。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决SpringBoot搭建MyBatisPlus中selectList遇到LambdaQueryWrapper报错问题

    解决SpringBoot搭建MyBatisPlus中selectList遇到LambdaQueryWrapper报错问题

    这篇文章主要介绍了解决SpringBoot搭建MyBatisPlus中selectList遇到LambdaQueryWrapper报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 通过Java视角简单谈谈局部性原理

    通过Java视角简单谈谈局部性原理

    程序的局部性原理是指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分,这篇文章主要给大家介绍了关于通过Java视角简单谈谈局部性原理的相关资料,需要的朋友可以参考下
    2021-07-07
  • SpringBoot整合Sa-Token实现 API 接口签名安全校验功能

    SpringBoot整合Sa-Token实现 API 接口签名安全校验功能

    这篇文章主要介绍了SpringBoot整合Sa-Token实现 API 接口签名安全校验功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • MybatisPlus查询数据日期格式化问题解决方法

    MybatisPlus查询数据日期格式化问题解决方法

    MyBatisPlus是MyBatis的增强工具,支持常规的CRUD操作以及复杂的联表查询等功能,这篇文章主要给大家介绍了关于MybatisPlus查询数据日期格式化问题的解决方法,需要的朋友可以参考下
    2023-10-10
  • 使用hutool进行ftp文件下载和上传详细代码示例

    使用hutool进行ftp文件下载和上传详细代码示例

    在开发Java项目时,FTP客户端是经常需要使用的工具,因为FTP协议在文件传输方面有着广泛的应用,这篇文章主要给大家介绍了关于使用hutool进行ftp文件下载和上传的相关资料,需要的朋友可以参考下
    2024-02-02
  • java中使用interrupt通知线程停止详析

    java中使用interrupt通知线程停止详析

    这篇文章主要介绍了java中使用interrupt通知线程停止详析,文章介绍的是使用interrupt来通知线程停止运行,而不是强制停止,详细内容需要的小伙伴可以参考一下
    2022-09-09
  • Springboot系列之kafka操作使用详解

    Springboot系列之kafka操作使用详解

    这篇文章主要为大家介绍了Springboot系列之kafka操作使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 使用Feign配置请求头以及支持Https协议

    使用Feign配置请求头以及支持Https协议

    这篇文章主要介绍了使用Feign配置请求头以及支持Https协议,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 浅谈HashMap中7种遍历方式的性能分析

    浅谈HashMap中7种遍历方式的性能分析

    本文先从HashMap的遍历方法讲起,然后再从性能、原理以及安全性等方面,来分析HashMap各种遍历方式的优势与不足
    2021-06-06
  • springBoot整合rabbitmq测试常用模型小结

    springBoot整合rabbitmq测试常用模型小结

    这篇文章主要介绍了springBoot整合rabbitmq并测试五种常用模型,本文主要针对前五种常用模型,在spirngboot框架的基础上整合rabbitmq并进行测试使用,需要的朋友可以参考下
    2022-01-01

最新评论