关于QueryWrapper,实现MybatisPlus多表关联查询方式
作者:mr_foxsand 发布时间:2021-10-15 07:24:59
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”) |
来源:https://blog.csdn.net/mr_foxsand/article/details/121356965


猜你喜欢
- Spring Cloud Gateway介绍前段时间刚刚发布了Spring Boot 2正式版,Spring Cloud Gateway基于
- 大家最近都在讨论新鲜技术-flutter,小编也在学习中,遇到大家都遇到的问题,底部导航。下面给大家贴出底部导航的编写,主要参考了lime这
- 1 编程语言简介编程语言(programming language)可以简单的理解为一种计算机和人都能识别的语言。一种计算机语言让程序员能够
- 1.什么是mybatis动态sql看到动态,我们就应该想到,这是一个可以变化的sql语句MyBatis的动态SQL是基于OGNL表达式的,它
- import java.awt.*; import java.util.*; import javax.swing.*; public cl
- C#中保存Session的三种方法及Web.Config设置保存session到sql server;,需要指定Sql Server;服务器
- Java5 在 java.util.concurrent 包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。读/写锁的 Ja
- 选择排序选择排序是一种简单直观的排序算法,它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未
- 本文实例为大家分享了Android中使用定时器的三种方法,供大家参考,具体内容如下图示:因为都比较简单,所以就直接贴代码(虑去再次点击停止的
- 即只能在组件布局代码后,或者在组件的前面添加注释。#注释格式:Android的XML文件注释一般采用 <!--注释内容 -->的
- 问题:对于多线程编程,很多时候往往需要向线程中传递多个参数,而C#中的线程只接收1个object类型的参数(如下):Thread t = n
- 本文主要介绍了C# 泛型字典 Dictionary的使用详解,分享给大家,具体如下:泛型最常见的用途是泛型集合,命名空间System.Col
- FreeMarker 是一个采用 Java 开发的模版引擎,是一个基于模版生成文本的通用工具。 它被设计用来生成 HTML Web 页面,特
- 看书的时候被一段代码能凌乱啦,代码是这样的:package 继承;abstract class People {
- 数组数组时相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成其中,每一个数据称作一个数组元素,每一个数组
- JAVA源码编译由三个过程组成:1、源码编译机制。2、类加载机制3、类执行机制我们这里主要介绍编译和类加载这两种机制。一、源码编译代码编译由
- 本文实例讲述了C#读写INI文件的方法。分享给大家供大家参考。具体如下:虽然微软早已经建议在WINDOWS中用注册表代替INI文件,但是在实
- 本文为大家分享了C#实现窗体全屏的具体代码,供大家参考,具体内容如下方法一:不过此方法有时候会出现莫名的bug//程序启动路径,与生成程序的
- Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建
- Android11 读写权限申请Android11系统对应用写入权限做了严格的限制。本文介绍如何获取文件读写权限。项目中 build.gra