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

2022-07-18,,,

目录
  • 使用querywrapper实现复杂查询
  • 自定义的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来查,那可以设定注解有优先等级来解决。

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

《MybatisPlus使用queryWrapper如何实现复杂查询.doc》

下载本文的Word格式文档,以方便收藏与打印。