MybatisPlus使用queryWrapper如何实现复杂查询
程序员文章站
2022-06-14 23:19:50
目录使用querywrapper实现复杂查询自定义的querywrapper实现查询声明提要核心代码使用querywrapper实现复杂查询// mp实现负责查询操作 @test p...
使用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来查,那可以设定注解有优先等级来解决。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。