关于QueryWrapper,实现MybatisPlus多表关联查询方式

 更新时间:2022年01月11日 10:44:29   作者:mr_foxsand  
这篇文章主要介绍了关于QueryWrapper,实现MybatisPlus多表关联查询方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。

QueryWrapper实现MybatisPlus多表关联查询

1.dao层接口使用Select注解写SQL

重点:@Param("ew") Wrapper参数是必须,因为${ew.customSqlSegment} 底层其实就是where 条件,所以为了保证Wrapper不为空,service层代码中的Wrapper至少需要有一个条件:1 = 1

@Override
    @Select("select a.code as code , b.name as name , b.barcode as barcode ,  a.ware_code as wareCode , c.name as wareName , a.qty as qty , a.oprice as oprice , a.total as total , " +
            " a.id as id , a.create_by as createBy , a.create_date as createDate , a.update_by as updateBy , a.update_date as updateDate , a.status as status , a.remarks as remarks  " +
            "from sku_stock a , goods b , warehouse c " +
            "${ew.customSqlSegment} and a.code = b.code and a.ware_code = c.code")
    IPage<SkuStock> selectPage(IPage<SkuStock> page, @Param("ew")Wrapper<SkuStock> queryWrapper);

2.service层代码示例

service父类封装的findPage方法:

/**
     * 封装findPage
     * @param entity
     * @param search  Map中的key:";"为保留关键字,拆分数组,仅支持最大长度2的数组,
     *                下标0:QueryWrapper查询条件中的列名(支持多表关联查询的表别名 + 列名方式,需要dao层接口支持)
     *                下标1: QueryWrapper中不同的查询条件,eq:等于,ge:大于等..... todo:请自行完善Mybatis eq、ne、gt、lt、ge、le等
     *                Map中的value:QueryWrapper需要查询的值
     * @param args  QueryWrapper中order by 排序数组
     * @return
     */
    public IPage<T> findPage(T entity , Map<String , Object> search , String... args){
        long current = 1L;
        long size = 10L;
        if (EmptyUtil.isNoEmpty(ReflexUtil.getFieldValue(entity , "page")) && (long) ReflexUtil.getFieldValue(entity , "page") != 0){
            current = (long) ReflexUtil.getFieldValue(entity , "page");
        }
        if (EmptyUtil.isNoEmpty(ReflexUtil.getFieldValue(entity , "limit")) && (long) ReflexUtil.getFieldValue(entity , "limit") != 0){
            size = (long) ReflexUtil.getFieldValue(entity , "limit");
        }
 
        QueryWrapper<T> queryWrapper;
        if (EmptyUtil.isNoEmpty(search)){
            queryWrapper = new QueryWrapper<>();
            for (Map.Entry<String , Object> entry:search.entrySet()
                 ) {
                String[] key = entry.getKey().split(";");
                if (key.length > 1){
                    if (key[1].equals("eq")){
                        queryWrapper.eq(key[0] , entry.getValue());
                    }else if (key[1].equals("ge")){
                        queryWrapper.ge(key[0] , entry.getValue());
                    }else if (key[1].equals("lt")){
                        queryWrapper.lt(key[0] , entry.getValue());
                    }
                }else {
                    queryWrapper.like(entry.getKey() , entry.getValue());
                }
            }
        }else {
            queryWrapper = new QueryWrapper<>(entity);
        }
        queryWrapper.orderByAsc(args);
        return super.page(new Page<T>(current , size) , queryWrapper);
    }

service实现类方法:

public IPage<SkuStock> findPage(SkuStock entity, String... args) {
        Map<String , Object> search = null;
        search = new HashedMap();
        search.put("1;eq" , "1");
        if (EmptyUtil.isNoEmpty(entity.getCode())
                || EmptyUtil.isNoEmpty(entity.getWareCode())
        ){
            if (EmptyUtil.isNoEmpty(entity.getCode())){
                search.put("code" , entity.getCode());
            }
            if (EmptyUtil.isNoEmpty(entity.getWareCode())){
                search.put("ware_code" , entity.getWareCode());
            }
        }else {
            long limit = entity.getLimit();
            long page = entity.getPage();
            entity = new SkuStock();
            entity.setLimit(limit);
            entity.setPage(page);
        }
        return super.findPage(entity , search , args);
    }

3.反射工具类

package org.bluedream.comm.utils; 
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
/**
 * @ClassName ReflexUtil
 * @Description TODO
 * @Author foxsand
 * @Data 2021-06-09 15:17
 * @Version
 */
public class ReflexUtil {
 
    /**
     * 返回 entity 对象的所有属性,包含父类
     * @param obj
     * @return
     */
    public static List<Field> getObjectFields(Object obj){
        Class clazz = obj.getClass();
        List<Field> fieldList = new ArrayList<>() ;
        while (clazz != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(clazz .getDeclaredFields()));
            clazz = clazz.getSuperclass(); //得到父类,然后赋给自己
        }
        return fieldList;
    }
 
    public static List<Field> getObjectFields(Class<?> clazz){
        List<Field> fieldList = new ArrayList<>() ;
        while (clazz != null){
            fieldList.addAll(Arrays.asList(clazz .getDeclaredFields()));
            clazz = clazz.getSuperclass(); //得到父类,然后赋给自己
        }
        return fieldList;
    }
 
    /**
     * 判断 Class entity 是否存在名称为 fieldName 的属性
     * @param fieldName
     * @param entity
     * @return
     */
    public static Boolean isField(String fieldName , Object entity){
        List<Field> fieldList = getObjectFields(entity);
        for (Field f1:fieldList
        ) {
            if (fieldName.equals(f1.getName()))
                return true;
        }
        return false;
    }
 
    /**
     * 返回 entity 对象中的所有方法,包含父类
     * @param entity
     * @return
     */
    public static List<Method> getObjectMethods(Object entity){
        Class<?> clazz = entity.getClass();
        List<Method> methods = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {//当父类为null的时候说明到达了最上层的父类(Object类).
            methods.addAll(Arrays.asList(clazz .getDeclaredMethods()));
            clazz = clazz.getSuperclass(); //得到父类,然后赋给自己
        }
        return methods;
    }
 
    public static List<Method> getObjectMethods(Class<?> clazz){
        List<Method> methods = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {//当父类为null的时候说明到达了最上层的父类(Object类).
            methods.addAll(Arrays.asList(clazz .getDeclaredMethods()));
            clazz = clazz.getSuperclass(); //得到父类,然后赋给自己
        }
        return methods;
    }
 
    /**
     * 判断 Class entity 是否存在名称为 methodName 的方法
     * @param methodName
     * @param entity
     * @return
     */
    public static Boolean isMethod(String methodName , Object entity){
        List<Method> methods = getObjectMethods(entity);
        for (Method m1:methods
        ) {
            if (methodName.equals(m1.getName()))
                return true;
        }
        return false;
    }
 
    /**
     * 循环向上转型, 获取对象的 DeclaredMethod
     * @param obj
     * @param methodName
     * @param parameterTypes  方法参数类型
     * @return
     */
    public static Method getDeclaredMethod(Object obj , String methodName , Class<?>...parameterTypes) {
        for (Class<?> clazz = obj.getClass(); clazz != Object.class && clazz != null; clazz = clazz.getSuperclass()) {
            try {
                return clazz.getDeclaredMethod(methodName, parameterTypes);
            } catch (Exception e) {
                // 这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
                // 如果这里的异常打印或者往外抛,则就不会执行clazz=clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return null;
    }
 
    public static Object invoke(Object object, String methodName, Class<?>[] parameterTypes,
                                Object[] parameters){
        Method method = getDeclaredMethod(object, methodName, parameterTypes);
        try {
            if (method != null){
                method.setAccessible(true);
                // 调用object 的 method 所代表的方法,其方法的参数是 parameters
                return method.invoke(object, parameters);
            }
        }catch (Exception e1){
            e1.printStackTrace();
        }
        return null;
    }
 
    /**
     * 循环向上转型, 获取对象的 DeclaredField
     *
     * @param object
     *            : 子类对象
     * @param fieldName
     *            : 父类中的属性名
     * @return 父类中的属性对象
     */
 
    public static Field getDeclaredField(Object object, String fieldName) {
        Field field = null; 
        Class<?> clazz = object.getClass(); 
        for (; clazz != Object.class && clazz != null; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                return field;
            } catch (Exception e) {
                // 这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
                // 如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 
            }
        } 
        return null;
    }
 
    /**
     * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
     *
     * @param object
     *            : 子类对象
     * @param fieldName
     *            : 父类中的属性名
     * @param value
     *            : 将要设置的值
     */
 
    public static void setFieldValue(Object object, String fieldName, Object value) {
 
        // 根据 对象和属性名通过反射 调用上面的方法获取 Field对象
        Field field = getDeclaredField(object, fieldName);
 
        if (field != null){
            // 抑制Java对其的检查
            field.setAccessible(true);
            try {
                // 将 object 中 field 所代表的值 设置为 value
                field.set(object, value);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
     *
     * @param object
     *            : 子类对象
     * @param fieldName
     *            : 父类中的属性名
     * @return : 父类中的属性值
     */
 
    public static Object getFieldValue(Object object, String fieldName) {
        // 根据 对象和属性名通过反射 调用上面的方法获取 Field对象
        Field field = getDeclaredField(object, fieldName);
 
        if (field != null){
            // 抑制Java对其的检查
            field.setAccessible(true);
            try {
                // 获取 object 中 field 所代表的属性值
                return field.get(object);
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }  
}

4.判空工具类

package org.bluedream.comm.utils; 
import java.util.Collection;
import java.util.Map; 
public class EmptyUtil {
    //Suppress default constructor for noninstantiability
    private EmptyUtil(){
        throw new AssertionError();
    }
 
    public static boolean isEmpty(Object object){
        if (object == null){
            return true;
        }
        if (object instanceof int[]){
            return ((int[]) object).length == 0;
        }
        if (object instanceof double[]){
            return ((double[]) object).length == 0;
        }
        if (object instanceof long[]){
            return ((long[]) object).length == 0;
        }
        if (object instanceof byte[]){
            return ((byte[]) object).length == 0;
        }
        if (object instanceof short[]){
            return ((short[]) object).length == 0;
        }
        if (object instanceof float[]){
            return ((float[]) object).length == 0;
        }
        if (object instanceof char[]){
            return ((char[]) object).length == 0;
        }
        if (object instanceof Object[]){
            return ((Object[]) object).length == 0;
        }
        if (object instanceof CharSequence) {
            return ((CharSequence) object).length() == 0;
        }
        if (object instanceof Collection ){
            return ((Collection) object).isEmpty();
        }
        if (object instanceof Map){
            return ((Map) object).isEmpty();
        }
        return false;
    }
 
    public static boolean isNoEmpty(Object object){
        return !isEmpty(object);
    } 
}

MybatisPlus QueryWrapper简单用法

查询方式

说明

setSqlSelect

设置 SELECT 查询字段

where

WHERE 语句,拼接 +?WHERE 条件

and

AND 语句,拼接 +?AND 字段=值

andNew

AND 语句,拼接 +?AND (字段=值)

or

OR 语句,拼接 +?OR 字段=值

orNew

OR 语句,拼接 +?OR (字段=值)

eq

等于=

allEq

基于 map 内容等于=

ne

不等于<>

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

like

模糊查询 LIKE

notLike

模糊查询 NOT LIKE

in

IN 查询

notIn

NOT IN 查询

isNull

NULL 值查询

isNotNull

IS NOT NULL

groupBy

分组 GROUP BY

having

HAVING 关键词

orderBy

排序 ORDER BY

orderAsc

ASC 排序 ORDER BY

orderDesc

DESC 排序 ORDER BY

exists

EXISTS 条件语句

notExists

NOT EXISTS 条件语句

between

BETWEEN 条件语句

notBetween

NOT BETWEEN 条件语句

addFilter

自由拼接 SQL

last

拼接在最后,例如:last(“LIMIT 1”)

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

相关文章

  • 使用Java填充Word模板的方法详解

    使用Java填充Word模板的方法详解

    Java填充Word模板是一种将动态数据插入到Word文档模板中生成最终文档的过程,通常用于批量创建包含个人信息、报告结果或其他动态内容的文档,本文给大家介绍了使用Java填充Word模板的方法,需要的朋友可以参考下
    2024-07-07
  • 详解在Spring中如何自动创建代理

    详解在Spring中如何自动创建代理

    这篇文章主要介绍了详解在Spring中如何自动创建代理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • IDEA中如何查找jar包之间的依赖关系并忽略依赖的某个包

    IDEA中如何查找jar包之间的依赖关系并忽略依赖的某个包

    这篇文章主要介绍了IDEA中如何查找jar包之间的依赖关系并忽略依赖的某个包?本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Spring @Order注解使用详解

    Spring @Order注解使用详解

    注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响
    2022-08-08
  • springboot整合Dubbo与Feign的实现 (无注册中心)

    springboot整合Dubbo与Feign的实现 (无注册中心)

    本文主要介绍了springboot整合Dubbo与Feign的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • java8中parallelStream性能测试及结果分析

    java8中parallelStream性能测试及结果分析

    本篇文章给大家用代码实例做了segmentfaultjava8中parallelStream性能测试,并对测试结果做了说明,需要的朋友学习下吧。
    2018-01-01
  • mybatis之如何获取表中某一列的最大值

    mybatis之如何获取表中某一列的最大值

    这篇文章主要介绍了mybatis之如何获取表中某一列的最大值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java项目如何打包成Jar的实现步骤

    Java项目如何打包成Jar的实现步骤

    一般情况下我们都是使用Java项目直接部署发布,有时需要我们将写好的项目打成jar包,方便后期调用,本文主要介绍了Java项目如何打包成Jar,感兴趣的可以了解一下
    2023-11-11
  • SpringSecurity+Mysql数据库实现用户安全登录认证的实践

    SpringSecurity+Mysql数据库实现用户安全登录认证的实践

    Spring Security 是一个提供身份认证、授权和防范常见攻击的安全权限框架,本文主要介绍了SpringSecurity+Mysql数据库实现用户安全登录认证的实践,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08
  • 深入学习java枚举的应用

    深入学习java枚举的应用

    本篇是关于java深入提高学习的相关知识,介绍了枚举的应用等方面内容,有兴趣的朋友参考学习下吧。
    2018-01-01

最新评论