Ver código fonte

修改批量查询

hmy 1 ano atrás
pai
commit
eb4b01568f

+ 6 - 0
src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java

@@ -7,6 +7,12 @@ public class PageParam implements Serializable {
 	private static final long serialVersionUID = 3358233066786644726L;
 	private static final Integer PAGE_NO = 1;
 	private static final Integer PAGE_SIZE = 10;
+	/**
+	 * 每页条数 - 不分页
+	 *
+	 * 例如说,导出接口,可以设置 {@link #pageSize} 为 -1 不分页,查询所有数据。
+	 */
+	public static final Integer PAGE_SIZE_NONE = -1;
 
 	public Integer getPageNo() {
 		return pageNo;

+ 18 - 0
src/main/java/cn/iocoder/yudao/framework/common/pojo/SortablePageParam.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.framework.common.pojo;
+
+import java.util.List;
+
+public class SortablePageParam extends PageParam {
+
+	private static final long serialVersionUID = 293281123180737878L;
+	private List<SortingField> sortingFields;
+
+	public List<SortingField> getSortingFields() {
+		return sortingFields;
+	}
+
+	public void setSortingFields(List<SortingField> sortingFields) {
+		this.sortingFields = sortingFields;
+	}
+
+}

+ 165 - 110
src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java

@@ -1,8 +1,10 @@
 package cn.iocoder.yudao.framework.mybatis.core.mapper;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.util.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
+import cn.iocoder.yudao.framework.common.pojo.SortingField;
 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -12,6 +14,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.baomidou.mybatisplus.extension.toolkit.Db;
 import com.github.yulichang.base.MPJBaseMapper;
+import com.github.yulichang.interfaces.MPJBaseJoin;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.Collection;
@@ -20,117 +24,168 @@ import java.util.List;
 /**
  * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
  *
- * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力 2.
- * {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力
+ * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力
+ * 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力
  */
 public interface BaseMapperX<T> extends MPJBaseMapper<T> {
 
-	default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
-		// MyBatis Plus 查询
-		IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
-		selectPage(mpPage, queryWrapper);
-		// 转换返回
-		return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
-	}
-
-	default T selectOne(String field, Object value) {
-		return selectOne(new QueryWrapper<T>().eq(field, value));
-	}
-
-	default T selectOne(SFunction<T, ?> field, Object value) {
-		return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
-	}
-
-	default T selectOne(String field1, Object value1, String field2, Object value2) {
-		return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
-	}
-
-	default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
-		return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
-	}
-
-	default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
-			SFunction<T, ?> field3, Object value3) {
-		return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
-	}
-
-	default Long selectCount() {
-		return selectCount(new QueryWrapper<>());
-	}
-
-	default Long selectCount(String field, Object value) {
-		return selectCount(new QueryWrapper<T>().eq(field, value));
-	}
-
-	default Long selectCount(SFunction<T, ?> field, Object value) {
-		return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
-	}
-
-	default List<T> selectList() {
-		return selectList(new QueryWrapper<>());
-	}
-
-	default List<T> selectList(String field, Object value) {
-		return selectList(new QueryWrapper<T>().eq(field, value));
-	}
-
-	default List<T> selectList(SFunction<T, ?> field, Object value) {
-		return selectList(new LambdaQueryWrapper<T>().eq(field, value));
-	}
-
-	default List<T> selectList(String field, Collection<?> values) {
-		if (CollUtil.isEmpty(values)) {
-			return CollUtil.newArrayList();
-		}
-		return selectList(new QueryWrapper<T>().in(field, values));
-	}
-
-	default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
-		if (CollUtil.isEmpty(values)) {
-			return CollUtil.newArrayList();
-		}
-		return selectList(new LambdaQueryWrapper<T>().in(field, values));
-	}
-
-	default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
-		return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
-	}
-
-	/**
-	 * 批量插入,适合大量数据插入
-	 *
-	 * @param entities 实体们
-	 */
-	default boolean insertBatch(Collection<T> entities) {
-
-		return Db.saveBatch(entities);
-		// return b;
-	}
-
-	/**
-	 * 批量插入,适合大量数据插入
-	 *
-	 * @param entities 实体们
-	 * @param size     插入数量 Db.saveBatch 默认为 1000
-	 */
-	default boolean insertBatch(Collection<T> entities, int size) {
-		return Db.saveBatch(entities, size);
-	}
-
-	default void updateBatch(T update) {
-		update(update, new QueryWrapper<>());
-	}
-
-	default void updateBatch(Collection<T> entities) {
-		Db.updateBatchById(entities);
-	}
-
-	default void updateBatch(Collection<T> entities, int size) {
-		Db.updateBatchById(entities, size);
-	}
-
-	default void saveOrUpdateBatch(Collection<T> collection) {
-		Db.saveOrUpdateBatch(collection);
-	}
+    default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
+        return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper);
+    }
+
+    default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
+        return selectPage(pageParam, null, queryWrapper);
+    }
+
+    default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields, @Param("ew") Wrapper<T> queryWrapper) {
+        // 特殊:不分页,直接查询全部
+        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
+            List<T> list = selectList(queryWrapper);
+            return new PageResult<>(list, (long) list.size());
+        }
+
+        // MyBatis Plus 查询
+        IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
+        selectPage(mpPage, queryWrapper);
+        // 转换返回
+        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
+    }
+
+    default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
+        // 特殊:不分页,直接查询全部
+        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageNo())) {
+            List<D> list = selectJoinList(clazz, lambdaWrapper);
+            return new PageResult<>(list, (long) list.size());
+        }
+
+        // MyBatis Plus Join 查询
+        IPage<D> mpPage = MyBatisUtils.buildPage(pageParam);
+        mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper);
+        // 转换返回
+        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
+    }
+
+    default <DTO> PageResult<DTO> selectJoinPage(PageParam pageParam, Class<DTO> resultTypeClass, MPJBaseJoin<T> joinQueryWrapper) {
+        IPage<DTO> mpPage = MyBatisUtils.buildPage(pageParam);
+        selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper);
+        // 转换返回
+        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
+    }
+
+    default T selectOne(String field, Object value) {
+        return selectOne(new QueryWrapper<T>().eq(field, value));
+    }
+
+    default T selectOne(SFunction<T, ?> field, Object value) {
+        return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
+    }
+
+    default T selectOne(String field1, Object value1, String field2, Object value2) {
+        return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
+    }
+
+    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
+        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
+    }
+
+    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
+                        SFunction<T, ?> field3, Object value3) {
+        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
+                .eq(field3, value3));
+    }
+
+    default Long selectCount() {
+        return selectCount(new QueryWrapper<>());
+    }
+
+    default Long selectCount(String field, Object value) {
+        return selectCount(new QueryWrapper<T>().eq(field, value));
+    }
+
+    default Long selectCount(SFunction<T, ?> field, Object value) {
+        return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
+    }
+
+    default List<T> selectList() {
+        return selectList(new QueryWrapper<>());
+    }
+
+    default List<T> selectList(String field, Object value) {
+        return selectList(new QueryWrapper<T>().eq(field, value));
+    }
+
+    default List<T> selectList(SFunction<T, ?> field, Object value) {
+        return selectList(new LambdaQueryWrapper<T>().eq(field, value));
+    }
+
+    default List<T> selectList(String field, Collection<?> values) {
+        if (CollUtil.isEmpty(values)) {
+            return CollUtil.newArrayList();
+        }
+        return selectList(new QueryWrapper<T>().in(field, values));
+    }
+
+    default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
+        if (CollUtil.isEmpty(values)) {
+            return CollUtil.newArrayList();
+        }
+        return selectList(new LambdaQueryWrapper<T>().in(field, values));
+    }
+
+    @Deprecated
+    default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
+        return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
+    }
+
+    default List<T> selectList(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
+        return selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
+    }
+
+    /**
+     * 批量插入,适合大量数据插入
+     *
+     * @param entities 实体们
+     */
+    default Boolean insertBatch(Collection<T> entities) {
+        return Db.saveBatch(entities);
+    }
+
+    /**
+     * 批量插入,适合大量数据插入
+     *
+     * @param entities 实体们
+     * @param size     插入数量 Db.saveBatch 默认为 1000
+     */
+    default Boolean insertBatch(Collection<T> entities, int size) {
+        return Db.saveBatch(entities, size);
+    }
+
+    default int updateBatch(T update) {
+        return update(update, new QueryWrapper<>());
+    }
+
+    default Boolean updateBatch(Collection<T> entities) {
+        return Db.updateBatchById(entities);
+    }
+
+    default Boolean updateBatch(Collection<T> entities, int size) {
+        return Db.updateBatchById(entities, size);
+    }
+
+    default Boolean insertOrUpdate(T entity) {
+        return  Db.saveOrUpdate(entity);
+    }
+
+    default Boolean insertOrUpdateBatch(Collection<T> collection) {
+        return Db.saveOrUpdateBatch(collection);
+    }
+
+    default int delete(String field, String value) {
+        return delete(new QueryWrapper<T>().eq(field, value));
+    }
+
+    default int delete(SFunction<T, ?> field, Object value) {
+        return delete(new LambdaQueryWrapper<T>().eq(field, value));
+    }
 
 }

+ 112 - 0
src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/LambdaColumnWrapper.java

@@ -0,0 +1,112 @@
+package cn.iocoder.yudao.framework.mybatis.core.mapper;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Field;
+import java.util.concurrent.ConcurrentHashMap;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+/*
+ * lambda反序列化
+ * //http://www.uml.org.cn/j2ee/202301044.asp
+	// https://nickid2018.github.io/2021/12/02/Java%20ASM%E8%AF%A6%E8%A7%A3%EF%BC%9AMethodVisitor%E4%B8%8EOpcode%EF%BC%88%E4%BA%94%EF%BC%89invokedynamic%E3%80%81%E6%96%B9%E6%B3%95%E5%8F%A5%E6%9F%84%E3%80%81lambda/
+	// https://www.cnblogs.com/aldalee/p/16772505.html
+	// https://developer.aliyun.com/article/1118083
+	// https://cloud.tencent.com/developer/article/1943109
+	// https://juejin.cn/post/6961014377361833991
+ */
+public class LambdaColumnWrapper {
+	private static ConcurrentHashMap<String, SFunction<?, ?>> functionMap = new ConcurrentHashMap<>();
+	private static ConcurrentHashMap<String, Field> fieldMap = new ConcurrentHashMap<>();
+//	  default <R> Children le(SFunction<R, ?> column, Object val) {
+//	        return le(true, null, column, val);
+//	    }
+
+	/**
+	 * 先获得自己的属性,然后再获得父类的属性
+	 * 
+	 * @param <T>   查询的泛型
+	 * @param clazz
+	 * @return
+	 * @throws SecurityException
+	 * @throws NoSuchFieldException
+	 */
+	private static <T> Field reflectField(Class<T> clazz, String fieldName) throws Exception {
+		if (fieldMap.containsKey(clazz.getName() + fieldName)) {
+			return fieldMap.get(clazz.getName() + fieldName);
+		}
+		Class<?> tmpClazz = clazz;
+		Field field = null;
+		while (tmpClazz != null) {
+			try {
+				field = tmpClazz.getDeclaredField(fieldName);
+			} catch (Exception e) {
+			}
+			tmpClazz = tmpClazz.getSuperclass();
+		}
+		return field;
+	}
+
+	public static SFunction<?, ?> getSFunction(Class<?> entityClass, String fieldName) throws Exception {
+		if (functionMap.containsKey(entityClass.getName() + fieldName)) {
+			return functionMap.get(entityClass.getName() + fieldName);
+		}
+		Field field = reflectField(entityClass, fieldName);
+		// entityClass.getDeclaredField(fieldName);
+		if (field == null) {
+			throw ExceptionUtils.mpe("This class %s is not have field %s ", entityClass.getName(), fieldName);
+		}
+		SFunction<?, ?> func = null;
+		final MethodHandles.Lookup lookup = MethodHandles.lookup();
+		MethodType methodType = MethodType.methodType(field.getType(), entityClass);
+		final CallSite site;
+		String getFunName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
+		try {
+			// caller:方法查找对象,用于检查权限
+			// invokedName:表示Lambda表达式调用的方法名
+			// invokedType:表示Lambda表达式的类型
+			// samMethodType:表示函数式接口中的抽象方法类型
+			// implMethod:表示Lambda表达式要代替的方法句柄
+			// instantiatedMethodType:表示内部匿名类要实现的接口类型
+			// 该方法会返回一个CallSite对象,代表Lambda表达式的调用点。
+			// * CallSite altMetafactory(
+			// MethodHandles.Lookup caller,
+			// String invokedName,
+			// MethodType invokedType,
+			// MethodType samMethodType,
+			// MethodHandle implMethod,
+			// MethodType instantiatedMethodType,
+			// int flags,
+			// int markerInterfaceCount, // IF flags has MARKERS set
+			// Class... markerInterfaces, // IF flags has MARKERS set
+			// int bridgeCount, // IF flags has BRIDGES set
+			// MethodType... bridges // IF flags has BRIDGES set
+			// )
+			site = LambdaMetafactory.altMetafactory(
+					// 方法查找对象,用于检查权限
+					lookup,
+					// invokedName:表示Lambda表达式调用的方法名
+					"apply",
+					// 表示Lambda表达式的类型
+					MethodType.methodType(SFunction.class),
+					// samMethodType:表示函数式接口中的抽象方法类型
+					methodType,
+					// implMethod:表示Lambda表达式要代替的方法句柄
+					lookup.findVirtual(entityClass, getFunName, MethodType.methodType(field.getType())),
+					// instantiatedMethodType:表示内部匿名类要实现的接口类型
+					methodType,
+					// flags
+					LambdaMetafactory.FLAG_SERIALIZABLE);
+			func = (SFunction<?, ?>) site.getTarget().invokeExact();
+			functionMap.put(entityClass.getName() + field, func);
+			return func;
+		} catch (Throwable e) {
+			throw ExceptionUtils.mpe("This class %s is not have method %s ", entityClass.getName(), getFunName);
+		}
+	}
+
+
+
+}

+ 97 - 11
src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/PlusBaseMapperX.java

@@ -1,33 +1,32 @@
 package cn.iocoder.yudao.framework.mybatis.core.mapper;
 
 import java.beans.PropertyDescriptor;
-
 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
 import org.apache.ibatis.reflection.property.PropertyNamer;
-import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
 import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
 import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
 
-import java.util.function.Function;
-import java.util.stream.Collectors;
 //TODO 需要优化的两个东西,1.批量查询 2。是两表查询
 public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 	static final Log logger = LogFactory.getLog(PlusBaseMapperX.class);
-
 	/**
 	 * 博客地址:https://blog.csdn.net/qq_19266669/article/details/114369195
 	 * 查看AbstractLambdaWrapper通过方法得到字段名称
@@ -69,12 +68,14 @@ public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 
 	@SuppressWarnings("unchecked")
 	default Class<T> getEntityClass() {
-		return (Class<T>)ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0) ;
+		return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0);
 	}
+
 	@SuppressWarnings("unchecked")
 	default Class<T> currentMapperClass() {
-        return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0);
-    }
+		return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0);
+	}
+
 	default Map<String, ColumnCache> tryInitCache(Class<?> lambdaClass) {
 
 		final Class<T> entityClass = getEntityClass();
@@ -274,8 +275,8 @@ public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 	 * @param queryWrapper 实体对象封装操作类
 	 *                     {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
 	 */
-	default <E extends IPage<T>> E page(E page, T t,QueryMap... map) {
-		Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t,map);
+	default <E extends IPage<T>> E page(E page, T t, QueryMap... map) {
+		Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t, map);
 		try {
 			return selectPage(page, queryWrapper);
 		} catch (Exception e) {
@@ -283,6 +284,7 @@ public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 		}
 		return null;
 	}
+
 	/**
 	 * 翻页查询
 	 *
@@ -299,4 +301,88 @@ public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 		}
 		return null;
 	}
+
+	/**
+	 * 查询对象 连表查询返回记录集合
+	 *
+	 * @param wrapper joinWrapper
+	 * @param clazz   resultType
+	 * @param objs    查询条件
+	 */
+
+	/**
+	 * 根据 Wrapper 条件,查询总记录数
+	 *
+	 * @param wrapper joinWrapper
+	 */
+	default Long selectJoinCount(MPJLambdaWrapper<T> wrapper, Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinCount(wrapper);
+	}
+
+	/**
+	 * 连表查询返回一条记录
+	 *
+	 * @param wrapper joinWrapper
+	 * @param clazz   resultType
+	 */
+	default <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJLambdaWrapper<T> wrapper, Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinOne(clazz, wrapper);
+	}
+
+	/**
+	 * 连表查询返回Map
+	 *
+	 * @param wrapper joinWrapper
+	 */
+	default Map<String, Object> selectJoinMap(MPJLambdaWrapper<T> wrapper, Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinMap(wrapper);
+	}
+
+	/**
+	 * 连表查询返回记录集合
+	 *
+	 * @param wrapper joinWrapper
+	 * @param clazz   resultType
+	 */
+	default <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJLambdaWrapper<T> wrapper, Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinList(clazz, wrapper);
+	}
+
+	/**
+	 * 连表查询返回Map集合
+	 *
+	 * @param wrapper joinWrapper
+	 */
+	default List<Map<String, Object>> selectJoinMaps(MPJLambdaWrapper<T> wrapper, Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinMaps(wrapper);
+	}
+
+	/**
+	 * 连表查询返回记录集合并分页
+	 *
+	 * @param wrapper joinWrapper
+	 * @param clazz   resultType
+	 * @param <DTO>   分页返回对象
+	 */
+	default <DTO, P extends IPage<DTO>> P selectJoinPage(P page, Class<DTO> clazz, MPJLambdaWrapper<T> wrapper,
+			Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinPage(page, clazz, wrapper);
+	}
+
+	/**
+	 * 连表查询返回Map集合并分页
+	 *
+	 * @param wrapper joinWrapper
+	 */
+	default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page, MPJLambdaWrapper<T> wrapper,
+			Object... param) {
+		wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
+		return this.selectJoinMapsPage(page, wrapper);
+	}
 }

+ 253 - 0
src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/QueryLambdaUtil.java

@@ -0,0 +1,253 @@
+package cn.iocoder.yudao.framework.mybatis.core.mapper;
+
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.ibatis.ognl.OgnlRuntime;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.util.ObjectUtils;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.github.yulichang.interfaces.MPJBaseJoin;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
+
+import static cn.iocoder.yudao.framework.mybatis.core.mapper.LambdaColumnWrapper.*;
+/**
+ * @Description 拼接查询条件工具类
+ */
+public class QueryLambdaUtil {
+
+	/**
+	 * 得到父类的对象
+	 * 
+	 * @param <T>   查询的泛型
+	 * @param clazz
+	 * @return
+	 */
+	private static <T> List<Field> reflectForField(Class<T> clazz) {
+		Class<?> tmpClazz = clazz;
+		List<Field> fieldList = new ArrayList<>();
+		while (tmpClazz != null) {
+			// 处理去掉静态属性
+			for (Field f : tmpClazz.getDeclaredFields()) {
+				if (!Modifier.isStatic(f.getModifiers())) {
+					fieldList.add(f);
+				}
+			}
+			tmpClazz = tmpClazz.getSuperclass();
+		}
+		return fieldList;
+	}
+
+	/**
+	 * 拼接查询条件,将附加的值放在map里面查询
+	 *
+	 * @param obj 数据实体
+	 * @return void 返回参数说明
+	 * @exception/throws
+	 */
+	public static <T> MPJLambdaWrapper<T> convertQuery(MPJLambdaWrapper<T> queryWrapper, Object... objs) {
+		//
+		QueryMap param = new QueryMap();
+		if (ArrayUtils.isNotEmpty(objs)) {
+			Object lastObj = objs[objs.length - 1];
+			if (lastObj instanceof QueryMap) {
+				param = (QueryMap) lastObj;
+			}
+			// 判断最后一个是否是QueryMap
+			for (Object obj : objs) {
+				Class<?> clazz = obj.getClass();
+				try {
+					for (Field field : reflectForField(clazz)) {
+						TableField tableField = AnnotationUtils.getAnnotation(field, TableField.class);
+						// 字段没有TableField这个注解和有这个主机上false的
+						// 这里有可能没有注解,是使用了骆驼ming'm
+						if (tableField != null && !tableField.exist()) {
+							continue;
+						}
+						// 获取属性名
+						String name = field.getName();
+						// 声明属性描述对象
+						Method method = getMethod(clazz, name);
+						if (method == null) {
+							continue;
+						}
+						Object fieldValue = method.invoke(obj);
+						String fieldName;
+						if (tableField == null) {
+							fieldName = StringUtils.camelToUnderline(name);
+						} else {
+							fieldName = tableField.value();
+						}
+						// 默认是相等
+						QueryWapper queryWapperAnnotation = AnnotationUtils.getAnnotation(field, QueryWapper.class);
+						if (ObjectUtils.isEmpty(queryWapperAnnotation)) {
+							if (!ObjectUtils.isEmpty(fieldValue)) {
+								queryWrapper.eq(getSFunction(clazz, fieldName), fieldValue);
+							}
+						} else {
+							// 获取枚举
+							QueryKeyword[] queryWapperEnums = queryWapperAnnotation.value();
+							for (QueryKeyword queryWapperEnum : queryWapperEnums) {
+								// 拼接查询条件
+								switch (queryWapperEnum) {
+								case NE:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.ne(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								// 这里需要,修改为集合
+								case IN:
+									if (fieldValue != null && fieldValue.toString().contains(",")) {
+										List<String> result = Arrays.asList(fieldValue.toString().split(","));
+										if (!ObjectUtils.isEmpty(fieldValue)) {
+											queryWrapper.in(getSFunction(clazz, fieldName), result);
+										}
+									}
+									break;
+								case GT:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										if (!ObjectUtils.isEmpty(fieldValue)) {
+											queryWrapper.gt(getSFunction(clazz, fieldName), fieldValue);
+										}
+									}
+									break;
+								case EQ:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.eq(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case GE:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.ge(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case LT:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.lt(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case LE:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.le(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case LIKE:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.like(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case NOT_LIKE:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.notLike(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case LIKE_LEFT:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.likeLeft(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case LIKE_RIGHT:
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										queryWrapper.likeRight(getSFunction(clazz, fieldName), fieldValue);
+									}
+									break;
+								case DESC:
+									queryWrapper.orderByDesc(fieldName);
+									break;
+								case AND:
+									break;
+								case BETWEEN:
+									break;
+								case EXISTS:
+									break;
+								case GROUP_BY:
+									break;
+								case HAVING:
+									break;
+								case IS_NOT_NULL:
+									break;
+								case IS_NULL:
+									break;
+								case NOT:
+									break;
+								case NOT_BETWEEN:
+									break;
+								case NOT_EXISTS:
+									break;
+								case NOT_IN:
+									break;
+								case OR:
+									queryWrapper.or();
+									break;
+								case ORDER_BY:
+									break;
+								case ASC:
+									queryWrapper.orderByAsc(fieldName);
+									break;
+								case RANGE:
+									// 设置开始的值和结束的值
+									String[] attribute = queryWapperAnnotation.attribute();
+									String startRange = attribute[0];
+									// 声明属性描述对象
+									method = getMethod(clazz, startRange);
+									if (method != null) {
+										Object val = method.invoke(obj);
+										if (!ObjectUtils.isEmpty(val)) {
+											queryWrapper.ge(fieldName, val);
+										}
+									}
+									String endRange = attribute[1];
+									method = getMethod(clazz, endRange);
+									if (method != null) {
+										Object val = method.invoke(obj);
+										if (!ObjectUtils.isEmpty(val)) {
+											queryWrapper.le(fieldName, val);
+										}
+									}
+									// ---属性值查询结束的值----
+									// 通过传入的参数查询值
+									// 然后通过参数查询
+									Object val = param.get(attribute[0]);
+									if (!ObjectUtils.isEmpty(val)) {
+										queryWrapper.ge(fieldName, val);
+									}
+									// 然后通过参数查询
+									val = param.get(attribute[1]);
+									if (!ObjectUtils.isEmpty(val)) {
+										queryWrapper.le(fieldName, val);
+									}
+									break;
+								default:
+									break;
+								}
+							}
+						}
+					}
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+
+			}
+		}
+		return queryWrapper;
+	}
+
+	// 获取get方法
+	private static Method getMethod(Class<?> clazz, String filedName) throws Exception {
+//		String alpha = filedName.substring(0, 1).toUpperCase();
+//		String methodName = "get" + alpha + filedName.substring(1);
+//		PropertyDescriptor p = new PropertyDescriptor(filedName, beanClass);
+//		Method readMethod = p.getReadMethod();
+
+		return OgnlRuntime.getReadMethod(clazz, filedName);
+	}
+
+}