Bladeren bron

增加代码的单元测试

hmy 1 maand geleden
bovenliggende
commit
df83ec50b3

+ 18 - 0
pom.xml

@@ -14,6 +14,8 @@
 	<url>http://maven.apache.org</url>
 
 	<properties>
+		<maven.compiler.source>17</maven.compiler.source>
+		<maven.compiler.target>17</maven.compiler.target>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<mybatis-plus.version>3.5.4</mybatis-plus.version>
 		<spring.boot.version>3.3.13</spring.boot.version>
@@ -63,6 +65,18 @@
 			<artifactId>mybatis-plus-join-boot-starter</artifactId>
 			<version>1.5.4</version>
 		</dependency>
+
+		<!-- 测试依赖 -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.h2database</groupId>
+			<artifactId>h2</artifactId>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 	<dependencyManagement>
 		<dependencies>
@@ -105,6 +119,10 @@
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
 				<version>3.11.0</version>
+				<configuration>
+					<source>17</source>
+					<target>17</target>
+				</configuration>
 			</plugin>
 		</plugins>
 	</build>

+ 363 - 0
src/main/java/mybatisex/core/mapper/BaseMapperX.java

@@ -3,10 +3,13 @@ package mybatisex.core.mapper;
 import java.util.Collection;
 import java.util.List;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.github.yulichang.base.MPJBaseMapper;
 
 /**
@@ -325,4 +328,364 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
 		return update(entity);
 	}
 
+	// ========== Lambda 表达式查询方法 ==========
+
+	// Lambda selectOne
+	default T selectOne(SFunction<T, ?> column, Object value) {
+		return selectOne(new LambdaQueryWrapper<T>().eq(column, value));
+	}
+
+	default T selectOne(SFunction<T, ?> column, Collection<?> value) {
+		return selectOne(new LambdaQueryWrapper<T>().in(column, value));
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return selectOne(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2));
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return selectOne(new LambdaQueryWrapper<T>().in(column1, value1).in(column2, value2));
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return selectOne(new LambdaQueryWrapper<T>().eq(column1, value1).in(column2, value2));
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return selectOne(new LambdaQueryWrapper<T>().in(column1, value1).eq(column2, value2));
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2,
+			SFunction<T, ?> column3, Object value3) {
+		return selectOne(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2).eq(column3, value3));
+	}
+
+	// Lambda selectCount
+	default Long selectCount(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().eq(column, value));
+	}
+
+	default Long selectCount(SFunction<T, ?> column, Collection<?> value) {
+		return selectCount(new LambdaQueryWrapper<T>().in(column, value));
+	}
+
+	default Long selectCount(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return selectCount(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2));
+	}
+
+	default Long selectCount(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2,
+			Collection<?> value2) {
+		return selectCount(new LambdaQueryWrapper<T>().in(column1, value1).in(column2, value2));
+	}
+
+	default Long selectCount(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return selectCount(new LambdaQueryWrapper<T>().eq(column1, value1).in(column2, value2));
+	}
+
+	default Long selectCount(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return selectCount(new LambdaQueryWrapper<T>().in(column1, value1).eq(column2, value2));
+	}
+
+	// Lambda selectList
+	default List<T> selectList(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().eq(column, value));
+	}
+
+	default List<T> selectList(SFunction<T, ?> column, Collection<?> value) {
+		return selectList(new LambdaQueryWrapper<T>().in(column, value));
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return selectList(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2));
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2,
+			Collection<?> value2) {
+		return selectList(new LambdaQueryWrapper<T>().in(column1, value1).in(column2, value2));
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return selectList(new LambdaQueryWrapper<T>().eq(column1, value1).in(column2, value2));
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return selectList(new LambdaQueryWrapper<T>().in(column1, value1).eq(column2, value2));
+	}
+
+	// Lambda delete
+	default int delete(SFunction<T, ?> column, Object value) {
+		return delete(new LambdaQueryWrapper<T>().eq(column, value));
+	}
+
+	default int delete(SFunction<T, ?> column, Collection<?> value) {
+		return delete(new LambdaQueryWrapper<T>().in(column, value));
+	}
+
+	default int delete(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return delete(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2));
+	}
+
+	default int delete(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return delete(new LambdaQueryWrapper<T>().in(column1, value1).in(column2, value2));
+	}
+
+	default int delete(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return delete(new LambdaQueryWrapper<T>().eq(column1, value1).in(column2, value2));
+	}
+
+	default int delete(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return delete(new LambdaQueryWrapper<T>().in(column1, value1).eq(column2, value2));
+	}
+
+	// Lambda update
+	default int update(SFunction<T, ?> whereColumn, Object whereValue, SFunction<T, ?> setColumn, Object setValue) {
+		LambdaUpdateWrapper<T> wrapper = new LambdaUpdateWrapper<>();
+		wrapper.eq(whereColumn, whereValue);
+		wrapper.set(setColumn, setValue);
+		return update(wrapper);
+	}
+
+	default int update(SFunction<T, ?> whereColumn, Collection<?> whereValue, SFunction<T, ?> setColumn,
+			Object setValue) {
+		LambdaUpdateWrapper<T> wrapper = new LambdaUpdateWrapper<>();
+		wrapper.in(whereColumn, whereValue);
+		wrapper.set(setColumn, setValue);
+		return update(wrapper);
+	}
+
+	default int update(SFunction<T, ?> whereColumn1, Object whereValue1, SFunction<T, ?> whereColumn2,
+			Object whereValue2, SFunction<T, ?> setColumn, Object setValue) {
+		LambdaUpdateWrapper<T> wrapper = new LambdaUpdateWrapper<>();
+		wrapper.eq(whereColumn1, whereValue1);
+		wrapper.eq(whereColumn2, whereValue2);
+		wrapper.set(setColumn, setValue);
+		return update(wrapper);
+	}
+
+	// ========== 复杂查询条件方法(基于字段) ==========
+
+	// LIKE 查询
+	default List<T> selectLike(String field, Object value) {
+		return selectList(new QueryWrapper<T>().like(field, value));
+	}
+
+	default Long countLike(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().like(field, value));
+	}
+
+	// BETWEEN 查询
+	default List<T> selectBetween(String field, Object start, Object end) {
+		return selectList(new QueryWrapper<T>().between(field, start, end));
+	}
+
+	default Long countBetween(String field, Object start, Object end) {
+		return selectCount(new QueryWrapper<T>().between(field, start, end));
+	}
+
+	// GT (大于) 查询
+	default List<T> selectGt(String field, Object value) {
+		return selectList(new QueryWrapper<T>().gt(field, value));
+	}
+
+	default Long countGt(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().gt(field, value));
+	}
+
+	// GE (大于等于) 查询
+	default List<T> selectGe(String field, Object value) {
+		return selectList(new QueryWrapper<T>().ge(field, value));
+	}
+
+	default Long countGe(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().ge(field, value));
+	}
+
+	// LT (小于) 查询
+	default List<T> selectLt(String field, Object value) {
+		return selectList(new QueryWrapper<T>().lt(field, value));
+	}
+
+	default Long countLt(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().lt(field, value));
+	}
+
+	// LE (小于等于) 查询
+	default List<T> selectLe(String field, Object value) {
+		return selectList(new QueryWrapper<T>().le(field, value));
+	}
+
+	default Long countLe(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().le(field, value));
+	}
+
+	// NE (不等于) 查询
+	default List<T> selectNe(String field, Object value) {
+		return selectList(new QueryWrapper<T>().ne(field, value));
+	}
+
+	default Long countNe(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().ne(field, value));
+	}
+
+	// IS NULL 查询
+	default List<T> selectIsNull(String field) {
+		return selectList(new QueryWrapper<T>().isNull(field));
+	}
+
+	default Long countIsNull(String field) {
+		return selectCount(new QueryWrapper<T>().isNull(field));
+	}
+
+	// IS NOT NULL 查询
+	default List<T> selectIsNotNull(String field) {
+		return selectList(new QueryWrapper<T>().isNotNull(field));
+	}
+
+	default Long countIsNotNull(String field) {
+		return selectCount(new QueryWrapper<T>().isNotNull(field));
+	}
+
+	// EXISTS 检查
+	default boolean exists(String field, Object value) {
+		return selectCount(new QueryWrapper<T>().eq(field, value)) > 0;
+	}
+
+	default boolean exists(String field1, Object value1, String field2, Object value2) {
+		return selectCount(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2)) > 0;
+	}
+
+	// ========== 复杂查询条件方法(基于 Lambda) ==========
+
+	// Lambda LIKE 查询
+	default List<T> selectLike(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().like(column, value));
+	}
+
+	default Long countLike(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().like(column, value));
+	}
+
+	// Lambda BETWEEN 查询
+	default List<T> selectBetween(SFunction<T, ?> column, Object start, Object end) {
+		return selectList(new LambdaQueryWrapper<T>().between(column, start, end));
+	}
+
+	default Long countBetween(SFunction<T, ?> column, Object start, Object end) {
+		return selectCount(new LambdaQueryWrapper<T>().between(column, start, end));
+	}
+
+	// Lambda GT 查询
+	default List<T> selectGt(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().gt(column, value));
+	}
+
+	default Long countGt(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().gt(column, value));
+	}
+
+	// Lambda GE 查询
+	default List<T> selectGe(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().ge(column, value));
+	}
+
+	default Long countGe(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().ge(column, value));
+	}
+
+	// Lambda LT 查询
+	default List<T> selectLt(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().lt(column, value));
+	}
+
+	default Long countLt(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().lt(column, value));
+	}
+
+	// Lambda LE 查询
+	default List<T> selectLe(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().le(column, value));
+	}
+
+	default Long countLe(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().le(column, value));
+	}
+
+	// Lambda NE 查询
+	default List<T> selectNe(SFunction<T, ?> column, Object value) {
+		return selectList(new LambdaQueryWrapper<T>().ne(column, value));
+	}
+
+	default Long countNe(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().ne(column, value));
+	}
+
+	// Lambda IS NULL 查询
+	default List<T> selectIsNull(SFunction<T, ?> column) {
+		return selectList(new LambdaQueryWrapper<T>().isNull(column));
+	}
+
+	default Long countIsNull(SFunction<T, ?> column) {
+		return selectCount(new LambdaQueryWrapper<T>().isNull(column));
+	}
+
+	// Lambda IS NOT NULL 查询
+	default List<T> selectIsNotNull(SFunction<T, ?> column) {
+		return selectList(new LambdaQueryWrapper<T>().isNotNull(column));
+	}
+
+	default Long countIsNotNull(SFunction<T, ?> column) {
+		return selectCount(new LambdaQueryWrapper<T>().isNotNull(column));
+	}
+
+	// Lambda EXISTS 检查
+	default boolean exists(SFunction<T, ?> column, Object value) {
+		return selectCount(new LambdaQueryWrapper<T>().eq(column, value)) > 0;
+	}
+
+	default boolean exists(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return selectCount(new LambdaQueryWrapper<T>().eq(column1, value1).eq(column2, value2)) > 0;
+	}
+
+	// ========== 统计方法(基于字段) ==========
+
+	/**
+	 * 获取字段最大值
+	 * 
+	 * @param field 字段名(会自动验证,防止 SQL 注入)
+	 */
+	default Object selectMax(String field) {
+
+		return selectObjs(new QueryWrapper<T>().select("MAX(" + field + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段最小值
+	 * 
+	 * @param field 字段名(会自动验证,防止 SQL 注入)
+	 */
+	default Object selectMin(String field) {
+
+		return selectObjs(new QueryWrapper<T>().select("MIN(" + field + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段总和
+	 * 
+	 * @param field 字段名(会自动验证,防止 SQL 注入)
+	 */
+	default Object selectSum(String field) {
+
+		return selectObjs(new QueryWrapper<T>().select("SUM(" + field + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段平均值
+	 * 
+	 * @param field 字段名(会自动验证,防止 SQL 注入)
+	 */
+	default Object selectAvg(String field) {
+
+		return selectObjs(new QueryWrapper<T>().select("AVG(" + field + ")")).stream().findFirst().orElse(null);
+	}
+
 }

+ 34 - 0
src/main/java/mybatisex/core/mapper/PlusBaseMapperX.java

@@ -433,6 +433,40 @@ public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
 		return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
 	}
 
+	// ========== 统计方法(基于 Lambda) ==========
+
+	/**
+	 * 获取字段最大值(Lambda)
+	 */
+	default Object selectMax(SFunction<T, ?> column) {
+		String columnName = columnToString(column);
+		return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("MAX(" + columnName + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段最小值(Lambda)
+	 */
+	default Object selectMin(SFunction<T, ?> column) {
+		String columnName = columnToString(column);
+		return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("MIN(" + columnName + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段总和(Lambda)
+	 */
+	default Object selectSum(SFunction<T, ?> column) {
+		String columnName = columnToString(column);
+		return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("SUM(" + columnName + ")")).stream().findFirst().orElse(null);
+	}
+
+	/**
+	 * 获取字段平均值(Lambda)
+	 */
+	default Object selectAvg(SFunction<T, ?> column) {
+		String columnName = columnToString(column);
+		return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("AVG(" + columnName + ")")).stream().findFirst().orElse(null);
+	}
+
 	default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
 		// 特殊:不分页,直接查询全部
 		if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageNo())) {

+ 0 - 27
src/main/java/mybatisex/core/mapper/QueryEntity.java

@@ -1,27 +0,0 @@
-package mybatisex.core.mapper;
-import com.baomidou.mybatisplus.annotation.TableField;
-
-public class QueryEntity {
-	public String getStartDate() {
-		return startDate;
-	}
-
-	public void setStartDate(String startDate) {
-		this.startDate = startDate;
-	}
-
-	public String getEndDate() {
-		return endDate;
-	}
-
-	public void setEndDate(String endDate) {
-		this.endDate = endDate;
-	}
-
-	// 开始时间
-	@TableField(exist = false)
-	private String startDate;
-	// 结束时间
-	@TableField(exist = false)
-	private String endDate;
-}

+ 236 - 106
src/main/java/mybatisex/core/mapper/QueryLambdaUtil.java

@@ -7,9 +7,12 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.ibatis.ognl.OgnlRuntime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.util.ObjectUtils;
 
@@ -19,10 +22,12 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 
 /**
- * @Description 拼接查询条件工具类
+ * Lambda 表达式查询条件拼接工具类 支持通过注解自动构建查询条件
  */
 public class QueryLambdaUtil {
 
+	private static final Logger log = LoggerFactory.getLogger(QueryLambdaUtil.class);
+
 	/**
 	 * 得到父类的对象
 	 * 
@@ -48,23 +53,36 @@ public class QueryLambdaUtil {
 	/**
 	 * 拼接查询条件,将附加的值放在map里面查询
 	 *
-	 * @param obj 数据实体
-	 * @return void 返回参数说明
-	 * @exception/throws
+	 * @param queryWrapper 查询包装器
+	 * @param objs 数据实体对象(可以是多个,最后一个可以是 QueryMap)
+	 * @return MPJLambdaWrapper 查询条件包装器
 	 */
 	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
+		}
+		
+		// 获取查询目标实体类 T(通过反射从 queryWrapper 获取)
+		Class<T> targetEntityClass = getTargetEntityClass(queryWrapper);
+		if (targetEntityClass == null) {
+			log.warn("Cannot get target entity class from queryWrapper, query may fail");
+			return queryWrapper;
+		}
+		
+		// 判断最后一个是否是QueryMap,如果不是 QueryMap 则处理所有对象
+		if (ArrayUtils.isNotEmpty(objs)) {
 			for (Object obj : objs) {
-				Class<?> clazz = obj.getClass();
+				// 跳过 QueryMap 对象
+				if (obj instanceof QueryMap) {
+					continue;
+				}
+				Class<?> objClass = obj.getClass();
 				try {
-					for (Field field : reflectForField(clazz)) {
+					for (Field field : reflectForField(objClass)) {
 						TableField tableField = AnnotationUtils.getAnnotation(field, TableField.class);
 						// 字段没有TableField这个注解和有这个主机上false的
 
@@ -74,11 +92,18 @@ public class QueryLambdaUtil {
 						// 获取属性名
 						String name = field.getName();
 						// 声明属性描述对象
-						Method method = getMethod(clazz, name);
+						Method method = getMethod(objClass, name);
 						if (method == null) {
 							continue;
 						}
-						Object fieldValue = method.invoke(obj);
+						Object fieldValue;
+						try {
+							fieldValue = method.invoke(obj);
+						} catch (Exception e) {
+							log.debug("Failed to invoke getter method for field: {} in class: {}", name,
+									objClass.getName(), e);
+							continue;
+						}
 						String fieldName;
 						if (tableField == null) {
 							fieldName = StringUtils.camelToUnderline(name);
@@ -89,7 +114,8 @@ public class QueryLambdaUtil {
 						QueryWapper queryWapperAnnotation = AnnotationUtils.getAnnotation(field, QueryWapper.class);
 						if (ObjectUtils.isEmpty(queryWapperAnnotation)) {
 							if (!ObjectUtils.isEmpty(fieldValue)) {
-								queryWrapper.eq(getSFunction(clazz, fieldName), fieldValue);
+								// 使用目标实体类 T 创建 Lambda 表达式,而不是传入对象的类
+								queryWrapper.eq(getSFunction(targetEntityClass, fieldName), fieldValue);
 							}
 						} else {
 							// 获取枚举
@@ -99,67 +125,69 @@ public class QueryLambdaUtil {
 								switch (queryWapperEnum) {
 								case NE:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.ne(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.ne(getSFunction(targetEntityClass, 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);
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										if (fieldValue instanceof Collection) {
+											queryWrapper.in(getSFunction(targetEntityClass, fieldName), (Collection<?>) fieldValue);
+										} else if (fieldValue.toString().contains(",")) {
+											List<String> result = Arrays.asList(fieldValue.toString().split(","));
+											queryWrapper.in(getSFunction(targetEntityClass, fieldName), result);
+										} else {
+											queryWrapper.in(getSFunction(targetEntityClass, fieldName), fieldValue);
 										}
 									}
 									break;
 								case GT:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										if (!ObjectUtils.isEmpty(fieldValue)) {
-											queryWrapper.gt(getSFunction(clazz, fieldName), fieldValue);
-										}
+										queryWrapper.gt(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case EQ:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.eq(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.eq(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case GE:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.ge(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.ge(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case LT:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.lt(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.lt(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case LE:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.le(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.le(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case LIKE:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.like(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.like(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case NOT_LIKE:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.notLike(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.notLike(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case LIKE_LEFT:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.likeLeft(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.likeLeft(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case LIKE_RIGHT:
 									if (!ObjectUtils.isEmpty(fieldValue)) {
-										queryWrapper.likeRight(getSFunction(clazz, fieldName), fieldValue);
+										queryWrapper.likeRight(getSFunction(targetEntityClass, fieldName), fieldValue);
 									}
 									break;
 								case DESC:
-									queryWrapper.orderByDesc(fieldName);
+									queryWrapper.orderByDesc(getSFunction(targetEntityClass, fieldName));
 									break;
 								case AND:
 									// 支持通过attribute指定多字段AND连接(格式:{"field1", "field2"})
@@ -167,13 +195,17 @@ public class QueryLambdaUtil {
 									if (ArrayUtils.isNotEmpty(andFields)) {
 										for (String andField : andFields) {
 											// 反射获取关联字段的值
-											Method andMethod = getMethod(clazz, andField);
+											Method andMethod = getMethod(objClass, andField);
 											if (andMethod != null) {
-												Object andValue = andMethod.invoke(obj);
-												if (!ObjectUtils.isEmpty(andValue)) {
-													// 转换为数据库字段名
-													String dbAndField = getDbFieldName(clazz, andField, tableField);
-													queryWrapper.eq(getSFunction(clazz, dbAndField), andValue);
+												try {
+													Object andValue = andMethod.invoke(obj);
+													if (!ObjectUtils.isEmpty(andValue)) {
+														// 转换为数据库字段名
+														String dbAndField = getDbFieldName(objClass, andField, tableField);
+														queryWrapper.eq(getSFunction(targetEntityClass, dbAndField), andValue);
+													}
+												} catch (Exception e) {
+													log.warn("Failed to invoke method for AND field: {}", andField, e);
 												}
 											}
 										}
@@ -183,18 +215,35 @@ public class QueryLambdaUtil {
 								case BETWEEN:
 									// 通过attribute指定开始/结束字段(格式:{"startField", "endField"})
 									String[] betweenFields = queryWapperAnnotation.attribute();
-									if (betweenFields.length == 2) {
-										// 获取开始值
-										Method startMethod = getMethod(clazz, betweenFields[0]);
-										Object startVal = startMethod != null ? startMethod.invoke(obj) : null;
-										// 获取结束值
-										Method endMethod = getMethod(clazz, betweenFields[1]);
-										Object endVal = endMethod != null ? endMethod.invoke(obj) : null;
-										// 两个值都存在时才添加BETWEEN条件
-										if (!ObjectUtils.isEmpty(startVal) && !ObjectUtils.isEmpty(endVal)) {
-											queryWrapper.between(getSFunction(clazz, fieldName), startVal, endVal);
+									if (betweenFields == null || betweenFields.length < 2) {
+										log.warn("BETWEEN query requires 2 attributes, but got: {}",
+												betweenFields == null ? 0 : betweenFields.length);
+										break;
+									}
+									// 获取开始值
+									Method startMethod = getMethod(objClass, betweenFields[0]);
+									Object startVal = null;
+									if (startMethod != null) {
+										try {
+											startVal = startMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for startField: {}", betweenFields[0], e);
 										}
 									}
+									// 获取结束值
+									Method endMethod = getMethod(objClass, betweenFields[1]);
+									Object endVal = null;
+									if (endMethod != null) {
+										try {
+											endVal = endMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for endField: {}", betweenFields[1], e);
+										}
+									}
+									// 两个值都存在时才添加BETWEEN条件
+									if (!ObjectUtils.isEmpty(startVal) && !ObjectUtils.isEmpty(endVal)) {
+										queryWrapper.between(getSFunction(targetEntityClass, fieldName), startVal, endVal);
+									}
 									break;
 
 								case GROUP_BY:
@@ -202,8 +251,8 @@ public class QueryLambdaUtil {
 									String[] groupFields = queryWapperAnnotation.attribute();
 									if (ArrayUtils.isNotEmpty(groupFields)) {
 										for (String groupField : groupFields) {
-											String dbGroupField = getDbFieldName(clazz, groupField, tableField);
-											queryWrapper.groupBy(getSFunction(clazz, dbGroupField));
+											String dbGroupField = getDbFieldName(objClass, groupField, tableField);
+											queryWrapper.groupBy(getSFunction(targetEntityClass, dbGroupField));
 										}
 									}
 									break;
@@ -218,12 +267,12 @@ public class QueryLambdaUtil {
 
 								case IS_NOT_NULL:
 									// 字段非空判断(无需值,直接添加条件)
-									queryWrapper.isNotNull(getSFunction(clazz, fieldName));
+									queryWrapper.isNotNull(getSFunction(targetEntityClass, fieldName));
 									break;
 
 								case IS_NULL:
 									// 字段为空判断(无需值,直接添加条件)
-									queryWrapper.isNull(getSFunction(clazz, fieldName));
+									queryWrapper.isNull(getSFunction(targetEntityClass, fieldName));
 									break;
 
 								case NOT:
@@ -231,18 +280,23 @@ public class QueryLambdaUtil {
 									String[] notFields = queryWapperAnnotation.attribute();
 									if (ArrayUtils.isNotEmpty(notFields)) {
 										String notField = notFields[0];
-										Method notMethod = getMethod(clazz, notField);
+										Method notMethod = getMethod(objClass, notField);
 										if (notMethod != null) {
-											Object notValue = notMethod.invoke(obj);
-											if (!ObjectUtils.isEmpty(notValue)) {
-												String dbNotField = getDbFieldName(clazz, notField, tableField);
-												queryWrapper.not(i -> {
-													try {
-														i.eq(getSFunction(clazz, dbNotField), notValue);
-													} catch (Exception e) {
-														e.printStackTrace();
-													}
-												});
+											try {
+												Object notValue = notMethod.invoke(obj);
+												if (!ObjectUtils.isEmpty(notValue)) {
+													String dbNotField = getDbFieldName(objClass, notField, tableField);
+													queryWrapper.not(i -> {
+														try {
+															i.eq(getSFunction(targetEntityClass, dbNotField), notValue);
+														} catch (Exception e) {
+															log.error("Failed to build NOT condition for field: {}",
+																	dbNotField, e);
+														}
+													});
+												}
+											} catch (Exception e) {
+												log.warn("Failed to invoke method for NOT field: {}", notField, e);
 											}
 										}
 									}
@@ -251,28 +305,55 @@ public class QueryLambdaUtil {
 								case NOT_BETWEEN:
 									// 同BETWEEN,取反逻辑
 									String[] notBetweenFields = queryWapperAnnotation.attribute();
-									if (notBetweenFields.length == 2) {
-										Method notStartMethod = getMethod(clazz, notBetweenFields[0]);
-										Object notStartVal = notStartMethod != null ? notStartMethod.invoke(obj) : null;
-										Method notEndMethod = getMethod(clazz, notBetweenFields[1]);
-										Object notEndVal = notEndMethod != null ? notEndMethod.invoke(obj) : null;
-										if (!ObjectUtils.isEmpty(notStartVal) && !ObjectUtils.isEmpty(notEndVal)) {
-											queryWrapper.notBetween(getSFunction(clazz, fieldName), notStartVal,
-													notEndVal);
+									if (notBetweenFields == null || notBetweenFields.length < 2) {
+										log.warn("NOT_BETWEEN query requires 2 attributes, but got: {}",
+												notBetweenFields == null ? 0 : notBetweenFields.length);
+										break;
+									}
+									Method notStartMethod = getMethod(objClass, notBetweenFields[0]);
+									Object notStartVal = null;
+									if (notStartMethod != null) {
+										try {
+											notStartVal = notStartMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for notStartField: {}",
+													notBetweenFields[0], e);
+										}
+									}
+									Method notEndMethod = getMethod(objClass, notBetweenFields[1]);
+									Object notEndVal = null;
+									if (notEndMethod != null) {
+										try {
+											notEndVal = notEndMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for notEndField: {}", notBetweenFields[1],
+													e);
 										}
 									}
+									if (!ObjectUtils.isEmpty(notStartVal) && !ObjectUtils.isEmpty(notEndVal)) {
+										queryWrapper.notBetween(getSFunction(targetEntityClass, fieldName), notStartVal, notEndVal);
+									}
 									break;
 
 								case EXISTS:
+									// EXISTS 子查询暂不支持,需要手动构建
+									log.debug("EXISTS query keyword is not yet implemented");
 									break;
 								case NOT_EXISTS:
+									// NOT EXISTS 子查询暂不支持,需要手动构建
+									log.debug("NOT_EXISTS query keyword is not yet implemented");
 									break;
 								case NOT_IN:
 									// 同IN,取反逻辑
-									if (fieldValue != null && fieldValue.toString().contains(",")) {
-										List<String> notInList = Arrays.asList(fieldValue.toString().split(","));
-										if (!ObjectUtils.isEmpty(notInList)) {
-											queryWrapper.notIn(getSFunction(clazz, fieldName), notInList);
+									if (!ObjectUtils.isEmpty(fieldValue)) {
+										if (fieldValue instanceof Collection) {
+											queryWrapper.notIn(getSFunction(targetEntityClass, fieldName),
+													(Collection<?>) fieldValue);
+										} else if (fieldValue.toString().contains(",")) {
+											List<String> notInList = Arrays.asList(fieldValue.toString().split(","));
+											queryWrapper.notIn(getSFunction(targetEntityClass, fieldName), notInList);
+										} else {
+											queryWrapper.notIn(getSFunction(targetEntityClass, fieldName), fieldValue);
 										}
 									}
 									break;
@@ -292,49 +373,64 @@ public class QueryLambdaUtil {
 											if (StringUtils.isBlank(orderField))
 												continue;
 											String direction = parts.length > 1 ? parts[1].trim().toUpperCase() : "ASC";
-											String dbOrderField = getDbFieldName(clazz, orderField, tableField);
+											String dbOrderField = getDbFieldName(objClass, orderField, tableField);
 											if ("DESC".equals(direction)) {
-												queryWrapper.orderByDesc(getSFunction(clazz, dbOrderField));
+												queryWrapper.orderByDesc(getSFunction(targetEntityClass, dbOrderField));
 											} else {
-												queryWrapper.orderByAsc(getSFunction(clazz, dbOrderField));
+												queryWrapper.orderByAsc(getSFunction(targetEntityClass, dbOrderField));
 											}
 										}
 									}
 									break;
 								case ASC:
-									queryWrapper.orderByAsc(fieldName);
+									queryWrapper.orderByAsc(getSFunction(targetEntityClass, fieldName));
 									break;
 								case RANGE:
 									// 设置开始的值和结束的值
 									String[] attribute = queryWapperAnnotation.attribute();
+									if (attribute == null || attribute.length < 2) {
+										log.warn("RANGE query requires 2 attributes, but got: {}",
+												attribute == null ? 0 : attribute.length);
+										break;
+									}
 									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 rangeStartMethod = getMethod(objClass, startRange);
+									Object rangeStartVal = null;
+									if (rangeStartMethod != null) {
+										try {
+											rangeStartVal = rangeStartMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for startRange: {}", startRange, e);
 										}
 									}
-									String endRange = attribute[1];
-									method = getMethod(clazz, endRange);
-									if (method != null) {
-										Object val = method.invoke(obj);
-										if (!ObjectUtils.isEmpty(val)) {
-											queryWrapper.le(fieldName, val);
+
+									Method rangeEndMethod = getMethod(objClass, endRange);
+									Object rangeEndVal = null;
+									if (rangeEndMethod != null) {
+										try {
+											rangeEndVal = rangeEndMethod.invoke(obj);
+										} catch (Exception e) {
+											log.warn("Failed to invoke method for endRange: {}", endRange, e);
 										}
 									}
-									// ---属性值查询结束的值----
-									// 通过传入的参数查询值
-									// 然后通过参数查询
-									Object val = param.get(attribute[0]);
-									if (!ObjectUtils.isEmpty(val)) {
-										queryWrapper.ge(fieldName, val);
+
+									// 如果对象属性没有值,则从 QueryMap 中获取
+									if (ObjectUtils.isEmpty(rangeStartVal)) {
+										rangeStartVal = param.get(startRange);
 									}
-									// 然后通过参数查询
-									val = param.get(attribute[1]);
-									if (!ObjectUtils.isEmpty(val)) {
-										queryWrapper.le(fieldName, val);
+									if (ObjectUtils.isEmpty(rangeEndVal)) {
+										rangeEndVal = param.get(endRange);
+									}
+
+									// 添加范围查询条件
+									if (!ObjectUtils.isEmpty(rangeStartVal)) {
+										queryWrapper.ge(getSFunction(targetEntityClass, fieldName), rangeStartVal);
+									}
+									if (!ObjectUtils.isEmpty(rangeEndVal)) {
+										queryWrapper.le(getSFunction(targetEntityClass, fieldName), rangeEndVal);
 									}
 									break;
 								default:
@@ -344,7 +440,7 @@ public class QueryLambdaUtil {
 						}
 					}
 				} catch (Exception e) {
-					e.printStackTrace();
+					log.error("Failed to process query conditions for class: {}", objClass.getName(), e);
 				}
 
 			}
@@ -353,6 +449,34 @@ public class QueryLambdaUtil {
 	}
 
 	/**
+	 * 从 MPJLambdaWrapper 中获取目标实体类 T
+	 * 
+	 * @param queryWrapper 查询包装器
+	 * @return 目标实体类,如果获取失败则返回 null
+	 */
+	@SuppressWarnings("unchecked")
+	private static <T> Class<T> getTargetEntityClass(MPJLambdaWrapper<T> queryWrapper) {
+		try {
+			// 通过反射获取 queryWrapper 的 entityClass 字段
+			Field entityClassField = queryWrapper.getClass().getSuperclass().getDeclaredField("entityClass");
+			entityClassField.setAccessible(true);
+			return (Class<T>) entityClassField.get(queryWrapper);
+		} catch (Exception e) {
+			log.debug("Failed to get entityClass from queryWrapper via reflection, trying alternative method", e);
+			try {
+				// 尝试从父类获取
+				Field entityClassField = queryWrapper.getClass().getSuperclass().getSuperclass()
+						.getDeclaredField("entityClass");
+				entityClassField.setAccessible(true);
+				return (Class<T>) entityClassField.get(queryWrapper);
+			} catch (Exception e2) {
+				log.warn("Cannot get target entity class from queryWrapper", e2);
+				return null;
+			}
+		}
+	}
+
+	/**
 	 * 获取数据库字段名(处理TableField注解)
 	 */
 	private static <T> String getDbFieldName(Class<T> clazz, String fieldName, TableField tableField) {
@@ -363,14 +487,20 @@ public class QueryLambdaUtil {
 		return StringUtils.camelToUnderline(fieldName);
 	}
 
-	// 获取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);
+	/**
+	 * 获取字段的 getter 方法
+	 * 
+	 * @param clazz     类对象
+	 * @param fieldName 字段名
+	 * @return getter 方法,如果不存在则返回 null
+	 */
+	private static Method getMethod(Class<?> clazz, String fieldName) {
+		try {
+			return OgnlRuntime.getReadMethod(clazz, fieldName);
+		} catch (Exception e) {
+			log.debug("Failed to get read method for field: {} in class: {}", fieldName, clazz.getName(), e);
+			return null;
+		}
 	}
 
 }

+ 169 - 102
src/main/java/mybatisex/core/mapper/QueryWrapperUtil.java

@@ -5,9 +5,12 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.ibatis.ognl.OgnlRuntime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.util.ObjectUtils;
 
@@ -17,15 +20,19 @@ import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 
 /**
- * @Description 拼接查询条件工具类
+ * 查询条件拼接工具类
+ * 支持通过注解自动构建 QueryWrapper 查询条件
  */
 public class QueryWrapperUtil {
+
+	private static final Logger log = LoggerFactory.getLogger(QueryWrapperUtil.class);
+
 	/**
-	 * 得到父类的对象
+	 * 获取类及其父类的所有非静态字段
 	 * 
 	 * @param <T>   查询的泛型
-	 * @param clazz
-	 * @return
+	 * @param clazz 类对象
+	 * @return 字段列表
 	 */
 	public static <T> List<Field> reflectForField(Class<T> clazz) {
 		Class<?> tmpClazz = clazz;
@@ -46,8 +53,8 @@ public class QueryWrapperUtil {
 	 * 拼接查询条件
 	 *
 	 * @param obj 数据实体
-	 * @return void 返回参数说明
-	 * @exception/throws
+	 * @param map 可选的查询参数映射
+	 * @return QueryWrapper 查询条件包装器
 	 */
 	public static <T> QueryWrapper<T> convertQuery(Object obj, QueryMap... map) {
 		QueryMap param = new QueryMap();
@@ -57,35 +64,26 @@ public class QueryWrapperUtil {
 		QueryWrapper<T> queryWrapper = new QueryWrapper<>();
 		Class<?> clazz = obj.getClass();
 		try {
-			// TODO 这里应该通过共有方法来进行反射
 			for (Field field : reflectForField(clazz)) {
-
-				// 抑制Java对修饰符的检查
-//				field.setAccessible(true);
-				// 获取属性值
-//				Object fieldValue = field.get(obj);
-//            String fieldValue = getFieldValue(obj ,field.getName()).toString();
 				TableField tableField = AnnotationUtils.getAnnotation(field, TableField.class);
-				// 字段没有TableField这个注解和有这个主机上false的
-				// 这里有可能没有注解,是使用了骆驼ming'm
+				// 字段没有 TableField 注解或 exist=false 时跳过
 				if (tableField != null && !tableField.exist()) {
 					continue;
 				}
-				// String methodName = "set" + filedName.substring(0, 1).toUpperCase() +
-				// filedName.substring(1);
 				// 获取属性名
 				String name = field.getName();
-				// 声明属性描述对象
-//				PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, clazz);
-//				Method method = clazz.getDeclaredMethod(propertyName);
-				// 获取getter方法
-//				Method method = propertyDescriptor.getReadMethod();
-				// String getMethod = getMethod(name);
+				// 获取 getter 方法
 				Method method = getMethod(clazz, name);
 				if (method == null) {
 					continue;
 				}
-				Object fieldValue = method.invoke(obj);
+				Object fieldValue;
+				try {
+					fieldValue = method.invoke(obj);
+				} catch (Exception e) {
+					log.warn("Failed to invoke getter method for field: {} in class: {}", name, clazz.getName(), e);
+					continue;
+				}
 				String fieldName;
 				if (tableField == null) {
 					fieldName = StringUtils.camelToUnderline(name);
@@ -105,15 +103,17 @@ public class QueryWrapperUtil {
 						case NE:
 							queryWrapper.ne(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
 							break;
-						// 这里需要,修改为集合
 						case IN:
-							if (fieldValue != null)
-								if (fieldValue.toString().contains(",")) {
+							if (!ObjectUtils.isEmpty(fieldValue)) {
+								if (fieldValue instanceof Collection) {
+									queryWrapper.in(true, fieldName, (Collection<?>) fieldValue);
+								} else if (fieldValue.toString().contains(",")) {
 									List<String> result = Arrays.asList(fieldValue.toString().split(","));
-									queryWrapper.in(!ObjectUtils.isEmpty(fieldValue), fieldName, result);
+									queryWrapper.in(true, fieldName, result);
 								} else {
-									queryWrapper.in(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
+									queryWrapper.in(true, fieldName, fieldValue);
 								}
+							}
 							break;
 						case GT:
 							queryWrapper.gt(!ObjectUtils.isEmpty(fieldValue), fieldName, fieldValue);
@@ -154,27 +154,52 @@ public class QueryWrapperUtil {
 									if (andMethod == null) {
 										continue;
 									}
-									Object andValue = andMethod.invoke(obj);
-									if (!ObjectUtils.isEmpty(andValue)) {
-										String dbAndField = getDbFieldName(clazz, andField);
-										queryWrapper.eq(true, dbAndField, andValue);
+									try {
+										Object andValue = andMethod.invoke(obj);
+										if (!ObjectUtils.isEmpty(andValue)) {
+											String dbAndField = getDbFieldName(clazz, andField);
+											queryWrapper.eq(true, dbAndField, andValue);
+										}
+									} catch (Exception e) {
+										log.warn("Failed to invoke method for AND field: {} in class: {}", 
+												andField, clazz.getName(), e);
 									}
 								}
 							}
 							break;
-						case BETWEEN:
+						case BETWEEN: {
 							// attribute指定开始/结束字段(格式:{"startField", "endField"})
 							String[] betweenFields = queryWapperAnnotation.attribute();
-							if (betweenFields.length == 2) {
-								Method startMethod = getMethod(clazz, betweenFields[0]);
-								Object startVal = startMethod != null ? startMethod.invoke(obj) : null;
-								Method endMethod = getMethod(clazz, betweenFields[1]);
-								Object endVal = endMethod != null ? endMethod.invoke(obj) : null;
-								boolean betweenCondition = !ObjectUtils.isEmpty(startVal)
-										&& !ObjectUtils.isEmpty(endVal);
-								queryWrapper.between(betweenCondition, fieldName, startVal, endVal);
+							if (betweenFields == null || betweenFields.length < 2) {
+								log.warn("BETWEEN query requires 2 attributes, but got: {}",
+										betweenFields == null ? 0 : betweenFields.length);
+								break;
+							}
+							Method betweenStartMethod = getMethod(clazz, betweenFields[0]);
+							Object betweenStartVal = null;
+							if (betweenStartMethod != null) {
+								try {
+									betweenStartVal = betweenStartMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for startField: {} in class: {}", 
+											betweenFields[0], clazz.getName(), e);
+								}
+							}
+							Method betweenEndMethod = getMethod(clazz, betweenFields[1]);
+							Object betweenEndVal = null;
+							if (betweenEndMethod != null) {
+								try {
+									betweenEndVal = betweenEndMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for endField: {} in class: {}", 
+											betweenFields[1], clazz.getName(), e);
+								}
 							}
+							boolean betweenCondition = !ObjectUtils.isEmpty(betweenStartVal)
+									&& !ObjectUtils.isEmpty(betweenEndVal);
+							queryWrapper.between(betweenCondition, fieldName, betweenStartVal, betweenEndVal);
 							break;
+						}
 						case EXISTS:
 							// attribute[0]传入EXISTS子查询SQL
 							String[] existsSql = queryWapperAnnotation.attribute();
@@ -215,26 +240,51 @@ public class QueryWrapperUtil {
 								String notField = notFields[0];
 								Method notMethod = getMethod(clazz, notField);
 								if (notMethod != null) {
-									Object notValue = notMethod.invoke(obj);
-									if (!ObjectUtils.isEmpty(notValue)) {
-										String dbNotField = getDbFieldName(clazz, notField);
-										queryWrapper.not(true, i -> i.eq(dbNotField, notValue));
+									try {
+										Object notValue = notMethod.invoke(obj);
+										if (!ObjectUtils.isEmpty(notValue)) {
+											String dbNotField = getDbFieldName(clazz, notField);
+											queryWrapper.not(true, i -> i.eq(dbNotField, notValue));
+										}
+									} catch (Exception e) {
+										log.warn("Failed to invoke method for NOT field: {} in class: {}", 
+												notField, clazz.getName(), e);
 									}
 								}
 							}
 							break;
-						case NOT_BETWEEN:
+						case NOT_BETWEEN: {
 							String[] notBetweenFields = queryWapperAnnotation.attribute();
-							if (notBetweenFields.length == 2) {
-								Method notStartMethod = getMethod(clazz, notBetweenFields[0]);
-								Object notStartVal = notStartMethod != null ? notStartMethod.invoke(obj) : null;
-								Method notEndMethod = getMethod(clazz, notBetweenFields[1]);
-								Object notEndVal = notEndMethod != null ? notEndMethod.invoke(obj) : null;
-								boolean notBetweenCondition = !ObjectUtils.isEmpty(notStartVal)
-										&& !ObjectUtils.isEmpty(notEndVal);
-								queryWrapper.notBetween(notBetweenCondition, fieldName, notStartVal, notEndVal);
+							if (notBetweenFields == null || notBetweenFields.length < 2) {
+								log.warn("NOT_BETWEEN query requires 2 attributes, but got: {}",
+										notBetweenFields == null ? 0 : notBetweenFields.length);
+								break;
+							}
+							Method notBetweenStartMethod = getMethod(clazz, notBetweenFields[0]);
+							Object notBetweenStartVal = null;
+							if (notBetweenStartMethod != null) {
+								try {
+									notBetweenStartVal = notBetweenStartMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for notStartField: {} in class: {}", 
+											notBetweenFields[0], clazz.getName(), e);
+								}
+							}
+							Method notBetweenEndMethod = getMethod(clazz, notBetweenFields[1]);
+							Object notBetweenEndVal = null;
+							if (notBetweenEndMethod != null) {
+								try {
+									notBetweenEndVal = notBetweenEndMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for notEndField: {} in class: {}", 
+											notBetweenFields[1], clazz.getName(), e);
+								}
 							}
+							boolean notBetweenCondition = !ObjectUtils.isEmpty(notBetweenStartVal)
+									&& !ObjectUtils.isEmpty(notBetweenEndVal);
+							queryWrapper.notBetween(notBetweenCondition, fieldName, notBetweenStartVal, notBetweenEndVal);
 							break;
+						}
 						case NOT_EXISTS:
 							String[] notExistsSql = queryWapperAnnotation.attribute();
 							if (ArrayUtils.isNotEmpty(notExistsSql) && !StringUtils.isBlank(notExistsSql[0])) {
@@ -242,10 +292,14 @@ public class QueryWrapperUtil {
 							}
 							break;
 						case NOT_IN:
-							if (fieldValue != null && fieldValue.toString().contains(",")) {
-								List<String> notInList = Arrays.asList(fieldValue.toString().split(","));
-								if (!ObjectUtils.isEmpty(notInList)) {
+							if (!ObjectUtils.isEmpty(fieldValue)) {
+								if (fieldValue instanceof Collection) {
+									queryWrapper.notIn(true, fieldName, (Collection<?>) fieldValue);
+								} else if (fieldValue.toString().contains(",")) {
+									List<String> notInList = Arrays.asList(fieldValue.toString().split(","));
 									queryWrapper.notIn(true, fieldName, notInList);
+								} else {
+									queryWrapper.notIn(true, fieldName, fieldValue);
 								}
 							}
 							break;
@@ -278,49 +332,56 @@ public class QueryWrapperUtil {
 						case ASC:
 							queryWrapper.orderByAsc(fieldName);
 							break;
-						case RANGE:
+						case RANGE: {
 							// 设置开始的值和结束的值
-							String[] attribute = queryWapperAnnotation.attribute();
-							String startRange = attribute[0];
-							// 声明属性描述对象
-//							getMethod = getMethod(startRange);
-//							method = ReflectionUtils.findMethod(clazz, getMethod);
-							method = getMethod(clazz, startRange);
-							if (method != null) {
-								Object val = method.invoke(obj);
-								if (!ObjectUtils.isEmpty(val)) {
-									queryWrapper.ge(fieldName, val);
+							String[] rangeAttributes = queryWapperAnnotation.attribute();
+							if (rangeAttributes == null || rangeAttributes.length < 2) {
+								break;
+							}
+							String rangeStartField = rangeAttributes[0];
+							String rangeEndField = rangeAttributes[1];
+							
+							// 优先从对象属性获取开始值
+							Method rangeStartMethod = getMethod(clazz, rangeStartField);
+							Object rangeStartVal = null;
+							if (rangeStartMethod != null) {
+								try {
+									rangeStartVal = rangeStartMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for rangeStartField: {} in class: {}", 
+											rangeStartField, clazz.getName(), e);
 								}
 							}
-							// 得到开始的属性值,通过反射设置属性值
-//							Field startRange = clazz.getDeclaredField(attribute[0]);
-//							startRange.setAccessible(true);
-//							Object val = startRange.get(obj);
-							// 结束的属性值,通过反射设置属性值
-							String endRange = attribute[1];
-							// getMethod = getMethod(endRange);
-							// 获取getter方法
-							// method = ReflectionUtils.findMethod(clazz, getMethod);
-							method = getMethod(clazz, endRange);
-							if (method != null) {
-								Object val = method.invoke(obj);
-								if (!ObjectUtils.isEmpty(val)) {
-									queryWrapper.le(fieldName, val);
+							
+							// 优先从对象属性获取结束值
+							Method rangeEndMethod = getMethod(clazz, rangeEndField);
+							Object rangeEndVal = null;
+							if (rangeEndMethod != null) {
+								try {
+									rangeEndVal = rangeEndMethod.invoke(obj);
+								} catch (Exception e) {
+									log.warn("Failed to invoke method for rangeEndField: {} in class: {}", 
+											rangeEndField, clazz.getName(), e);
 								}
 							}
-							// ---属性值查询结束的值----
-							// 通过传入的参数查询值
-							// 然后通过参数查询
-							Object val = param.get(attribute[0]);
-							if (!ObjectUtils.isEmpty(val)) {
-								queryWrapper.ge(fieldName, val);
+							
+							// 如果对象属性没有值,则从 QueryMap 中获取
+							if (ObjectUtils.isEmpty(rangeStartVal)) {
+								rangeStartVal = param.get(rangeStartField);
 							}
-							// 然后通过参数查询
-							val = param.get(attribute[1]);
-							if (!ObjectUtils.isEmpty(val)) {
-								queryWrapper.le(fieldName, val);
+							if (ObjectUtils.isEmpty(rangeEndVal)) {
+								rangeEndVal = param.get(rangeEndField);
+							}
+							
+							// 添加范围查询条件
+							if (!ObjectUtils.isEmpty(rangeStartVal)) {
+								queryWrapper.ge(fieldName, rangeStartVal);
+							}
+							if (!ObjectUtils.isEmpty(rangeEndVal)) {
+								queryWrapper.le(fieldName, rangeEndVal);
 							}
 							break;
+						}
 
 						default:
 							break;
@@ -331,7 +392,7 @@ public class QueryWrapperUtil {
 
 			}
 		} catch (Exception e) {
-			e.printStackTrace();
+			log.warn("Failed to process query conditions for class: {}", clazz.getName(), e);
 		}
 		return queryWrapper;
 
@@ -357,14 +418,20 @@ public class QueryWrapperUtil {
 		return StringUtils.camelToUnderline(fieldName);
 	}
 
-	// 获取get方法
-	public 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);
+	/**
+	 * 获取字段的 getter 方法
+	 * 
+	 * @param clazz     类对象
+	 * @param fieldName 字段名
+	 * @return getter 方法,如果不存在则返回 null
+	 */
+	public static Method getMethod(Class<?> clazz, String fieldName) {
+		try {
+			return OgnlRuntime.getReadMethod(clazz, fieldName);
+		} catch (Exception e) {
+			log.warn("Failed to get read method for field: {} in class: {}", fieldName, clazz.getName(), e);
+			return null;
+		}
 	}
 
 }

+ 485 - 0
src/main/java/mybatisex/core/service/AbstractService.java

@@ -280,6 +280,129 @@ public interface AbstractService<T> extends MPJBaseService<T> {
 
 	// 查询selectList----------------end----------------------
 
+	// ========== Lambda 表达式查询方法 ==========
+
+	// Lambda selectOne
+	default T selectOne(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectOne(column, value);
+	}
+
+	default T selectOne(SFunction<T, ?> column, Collection<?> value) {
+		return getBaseMapper().selectOne(column, value);
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectOne(column1, value1, column2, value2);
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().selectOne(column1, value1, column2, value2);
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().selectOne(column1, value1, column2, value2);
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectOne(column1, value1, column2, value2);
+	}
+
+	default T selectOne(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2,
+			SFunction<T, ?> column3, Object value3) {
+		return getBaseMapper().selectOne(column1, value1, column2, value2, column3, value3);
+	}
+
+	// Lambda count
+	default Long count(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectCount(column, value);
+	}
+
+	default Long count(SFunction<T, ?> column, Collection<?> value) {
+		return getBaseMapper().selectCount(column, value);
+	}
+
+	default Long count(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectCount(column1, value1, column2, value2);
+	}
+
+	default Long count(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().selectCount(column1, value1, column2, value2);
+	}
+
+	default Long count(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().selectCount(column1, value1, column2, value2);
+	}
+
+	default Long count(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectCount(column1, value1, column2, value2);
+	}
+
+	// Lambda selectList
+	default List<T> selectList(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectList(column, value);
+	}
+
+	default List<T> selectList(SFunction<T, ?> column, Collection<?> value) {
+		return getBaseMapper().selectList(column, value);
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectList(column1, value1, column2, value2);
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2,
+			Collection<?> value2) {
+		return getBaseMapper().selectList(column1, value1, column2, value2);
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().selectList(column1, value1, column2, value2);
+	}
+
+	default List<T> selectList(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().selectList(column1, value1, column2, value2);
+	}
+
+	// Lambda delete
+	default int delete(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().delete(column, value);
+	}
+
+	default int delete(SFunction<T, ?> column, Collection<?> value) {
+		return getBaseMapper().delete(column, value);
+	}
+
+	default int delete(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().delete(column1, value1, column2, value2);
+	}
+
+	default int delete(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().delete(column1, value1, column2, value2);
+	}
+
+	default int delete(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Collection<?> value2) {
+		return getBaseMapper().delete(column1, value1, column2, value2);
+	}
+
+	default int delete(SFunction<T, ?> column1, Collection<?> value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().delete(column1, value1, column2, value2);
+	}
+
+	// Lambda update
+	default int update(SFunction<T, ?> whereColumn, Object whereValue, SFunction<T, ?> setColumn, Object setValue) {
+		return getBaseMapper().update(whereColumn, whereValue, setColumn, setValue);
+	}
+
+	default int update(SFunction<T, ?> whereColumn, Collection<?> whereValue, SFunction<T, ?> setColumn,
+			Object setValue) {
+		return getBaseMapper().update(whereColumn, whereValue, setColumn, setValue);
+	}
+
+	default int update(SFunction<T, ?> whereColumn1, Object whereValue1, SFunction<T, ?> whereColumn2,
+			Object whereValue2, SFunction<T, ?> setColumn, Object setValue) {
+		return getBaseMapper().update(whereColumn1, whereValue1, whereColumn2, whereValue2, setColumn, setValue);
+	}
+
 	// 删除条件---equal--------------------start--------------------------------
 	default int delete(String field, Object value) {
 		return getBaseMapper().delete(field, value);
@@ -520,4 +643,366 @@ public interface AbstractService<T> extends MPJBaseService<T> {
 		return getBaseMapper().selectJoinMapsPage(page, wrapper, param);
 	}
 
+	// ========== 存在性检查方法 ==========
+
+	/**
+	 * 检查记录是否存在(基于字段)
+	 */
+	default boolean exists(String field, Object value) {
+		return getBaseMapper().exists(field, value);
+	}
+
+	/**
+	 * 检查记录是否存在(基于两个字段)
+	 */
+	default boolean exists(String field1, Object value1, String field2, Object value2) {
+		return getBaseMapper().exists(field1, value1, field2, value2);
+	}
+
+	/**
+	 * 检查记录是否存在(基于 Lambda)
+	 */
+	default boolean exists(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().exists(column, value);
+	}
+
+	/**
+	 * 检查记录是否存在(基于两个 Lambda 字段)
+	 */
+	default boolean exists(SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
+		return getBaseMapper().exists(column1, value1, column2, value2);
+	}
+
+	/**
+	 * 检查记录是否存在(基于实体对象)
+	 */
+	default boolean exists(T t) {
+		return count(t) > 0;
+	}
+
+	// ========== 复杂查询条件方法(基于字段) ==========
+
+	/**
+	 * LIKE 查询
+	 */
+	default List<T> selectLike(String field, Object value) {
+		return getBaseMapper().selectLike(field, value);
+	}
+
+	default Long countLike(String field, Object value) {
+		return getBaseMapper().countLike(field, value);
+	}
+
+	/**
+	 * BETWEEN 查询
+	 */
+	default List<T> selectBetween(String field, Object start, Object end) {
+		return getBaseMapper().selectBetween(field, start, end);
+	}
+
+	default Long countBetween(String field, Object start, Object end) {
+		return getBaseMapper().countBetween(field, start, end);
+	}
+
+	/**
+	 * GT (大于) 查询
+	 */
+	default List<T> selectGt(String field, Object value) {
+		return getBaseMapper().selectGt(field, value);
+	}
+
+	default Long countGt(String field, Object value) {
+		return getBaseMapper().countGt(field, value);
+	}
+
+	/**
+	 * GE (大于等于) 查询
+	 */
+	default List<T> selectGe(String field, Object value) {
+		return getBaseMapper().selectGe(field, value);
+	}
+
+	default Long countGe(String field, Object value) {
+		return getBaseMapper().countGe(field, value);
+	}
+
+	/**
+	 * LT (小于) 查询
+	 */
+	default List<T> selectLt(String field, Object value) {
+		return getBaseMapper().selectLt(field, value);
+	}
+
+	default Long countLt(String field, Object value) {
+		return getBaseMapper().countLt(field, value);
+	}
+
+	/**
+	 * LE (小于等于) 查询
+	 */
+	default List<T> selectLe(String field, Object value) {
+		return getBaseMapper().selectLe(field, value);
+	}
+
+	default Long countLe(String field, Object value) {
+		return getBaseMapper().countLe(field, value);
+	}
+
+	/**
+	 * NE (不等于) 查询
+	 */
+	default List<T> selectNe(String field, Object value) {
+		return getBaseMapper().selectNe(field, value);
+	}
+
+	default Long countNe(String field, Object value) {
+		return getBaseMapper().countNe(field, value);
+	}
+
+	/**
+	 * IS NULL 查询
+	 */
+	default List<T> selectIsNull(String field) {
+		return getBaseMapper().selectIsNull(field);
+	}
+
+	default Long countIsNull(String field) {
+		return getBaseMapper().countIsNull(field);
+	}
+
+	/**
+	 * IS NOT NULL 查询
+	 */
+	default List<T> selectIsNotNull(String field) {
+		return getBaseMapper().selectIsNotNull(field);
+	}
+
+	default Long countIsNotNull(String field) {
+		return getBaseMapper().countIsNotNull(field);
+	}
+
+	// ========== 复杂查询条件方法(基于 Lambda) ==========
+
+	/**
+	 * Lambda LIKE 查询
+	 */
+	default List<T> selectLike(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectLike(column, value);
+	}
+
+	default Long countLike(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countLike(column, value);
+	}
+
+	/**
+	 * Lambda BETWEEN 查询
+	 */
+	default List<T> selectBetween(SFunction<T, ?> column, Object start, Object end) {
+		return getBaseMapper().selectBetween(column, start, end);
+	}
+
+	default Long countBetween(SFunction<T, ?> column, Object start, Object end) {
+		return getBaseMapper().countBetween(column, start, end);
+	}
+
+	/**
+	 * Lambda GT 查询
+	 */
+	default List<T> selectGt(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectGt(column, value);
+	}
+
+	default Long countGt(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countGt(column, value);
+	}
+
+	/**
+	 * Lambda GE 查询
+	 */
+	default List<T> selectGe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectGe(column, value);
+	}
+
+	default Long countGe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countGe(column, value);
+	}
+
+	/**
+	 * Lambda LT 查询
+	 */
+	default List<T> selectLt(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectLt(column, value);
+	}
+
+	default Long countLt(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countLt(column, value);
+	}
+
+	/**
+	 * Lambda LE 查询
+	 */
+	default List<T> selectLe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectLe(column, value);
+	}
+
+	default Long countLe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countLe(column, value);
+	}
+
+	/**
+	 * Lambda NE 查询
+	 */
+	default List<T> selectNe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().selectNe(column, value);
+	}
+
+	default Long countNe(SFunction<T, ?> column, Object value) {
+		return getBaseMapper().countNe(column, value);
+	}
+
+	/**
+	 * Lambda IS NULL 查询
+	 */
+	default List<T> selectIsNull(SFunction<T, ?> column) {
+		return getBaseMapper().selectIsNull(column);
+	}
+
+	default Long countIsNull(SFunction<T, ?> column) {
+		return getBaseMapper().countIsNull(column);
+	}
+
+	/**
+	 * Lambda IS NOT NULL 查询
+	 */
+	default List<T> selectIsNotNull(SFunction<T, ?> column) {
+		return getBaseMapper().selectIsNotNull(column);
+	}
+
+	default Long countIsNotNull(SFunction<T, ?> column) {
+		return getBaseMapper().countIsNotNull(column);
+	}
+
+	// ========== 批量操作方法 ==========
+
+	/**
+	 * 批量删除(基于字段条件)
+	 */
+	default int deleteBatch(String field, Collection<?> values) {
+		return getBaseMapper().delete(field, values);
+	}
+
+	/**
+	 * 批量删除(基于 Lambda 字段条件)
+	 */
+	default int deleteBatch(SFunction<T, ?> column, Collection<?> values) {
+		return getBaseMapper().delete(column, values);
+	}
+
+	/**
+	 * 批量更新(基于字段条件)
+	 */
+	default int updateBatch(String field, Collection<?> values, String setField, Object setValue) {
+		return getBaseMapper().update(field, values, setField, setValue);
+	}
+
+	/**
+	 * 批量更新(基于 Lambda 字段条件)
+	 */
+	default int updateBatch(SFunction<T, ?> whereColumn, Collection<?> whereValues, SFunction<T, ?> setColumn,
+			Object setValue) {
+		return getBaseMapper().update(whereColumn, whereValues, setColumn, setValue);
+	}
+
+	// ========== 排序查询方法 ==========
+
+	/**
+	 * 查询列表并排序(基于字段,升序)
+	 */
+	default List<T> selectListOrderByAsc(String field, Object value, String orderField) {
+		return getBaseMapper().selectList(new QueryWrapper<T>().eq(field, value).orderByAsc(orderField));
+	}
+
+	/**
+	 * 查询列表并排序(基于字段,降序)
+	 */
+	default List<T> selectListOrderByDesc(String field, Object value, String orderField) {
+		return getBaseMapper().selectList(new QueryWrapper<T>().eq(field, value).orderByDesc(orderField));
+	}
+
+	/**
+	 * 查询列表并排序(基于 Lambda,升序)
+	 */
+	default List<T> selectListOrderByAsc(SFunction<T, ?> column, Object value, SFunction<T, ?> orderColumn) {
+		return getBaseMapper().selectList(
+				new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>().eq(column, value)
+						.orderByAsc(orderColumn));
+	}
+
+	/**
+	 * 查询列表并排序(基于 Lambda,降序)
+	 */
+	default List<T> selectListOrderByDesc(SFunction<T, ?> column, Object value, SFunction<T, ?> orderColumn) {
+		return getBaseMapper().selectList(
+				new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<T>().eq(column, value)
+						.orderByDesc(orderColumn));
+	}
+
+	// ========== 统计方法 ==========
+
+	/**
+	 * 获取字段最大值(基于字段)
+	 */
+	default Object selectMax(String field) {
+		return getBaseMapper().selectMax(field);
+	}
+
+	/**
+	 * 获取字段最小值(基于字段)
+	 */
+	default Object selectMin(String field) {
+		return getBaseMapper().selectMin(field);
+	}
+
+	/**
+	 * 获取字段总和(基于字段)
+	 */
+	default Object selectSum(String field) {
+		return getBaseMapper().selectSum(field);
+	}
+
+	/**
+	 * 获取字段平均值(基于字段)
+	 */
+	default Object selectAvg(String field) {
+		return getBaseMapper().selectAvg(field);
+	}
+
+	/**
+	 * 获取字段最大值(基于 Lambda)
+	 */
+	default Object selectMax(SFunction<T, ?> column) {
+		return getBaseMapper().selectMax(column);
+	}
+
+	/**
+	 * 获取字段最小值(基于 Lambda)
+	 */
+	default Object selectMin(SFunction<T, ?> column) {
+		return getBaseMapper().selectMin(column);
+	}
+
+	/**
+	 * 获取字段总和(基于 Lambda)
+	 */
+	default Object selectSum(SFunction<T, ?> column) {
+		return getBaseMapper().selectSum(column);
+	}
+
+	/**
+	 * 获取字段平均值(基于 Lambda)
+	 */
+	default Object selectAvg(SFunction<T, ?> column) {
+		return getBaseMapper().selectAvg(column);
+	}
+
 }

+ 0 - 22
src/main/java/mybatisex/datasource/core/enums/DataSourceEnum.java

@@ -1,22 +0,0 @@
-package mybatisex.datasource.core.enums;
-
-/**
- * 对应于多数据源中不同数据源配置
- *
- * 通过在方法上,使用 {@link com.baomidou.dynamic.datasource.annotation.DS} 注解,设置使用的数据源。
- * 注意,默认是 {@link #MASTER} 数据源
- *
- * 对应官方文档为 http://dynamic-datasource.com/guide/customize/Annotation.html
- */
-public interface DataSourceEnum {
-
-    /**
-     * 主库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Master} 注解
-     */
-    String MASTER = "master";
-    /**
-     * 从库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Slave} 注解
-     */
-    String SLAVE = "slave";
-
-}

File diff suppressed because it is too large
+ 1504 - 0
src/test/java/mybatisex/core/service/AbstractServiceTest.java


+ 27 - 0
src/test/java/mybatisex/core/service/TestConfiguration.java

@@ -0,0 +1,27 @@
+package mybatisex.core.service;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+
+import mybatisex.core.handler.DefaultDBFieldHandler;
+
+/**
+ * 测试配置类
+ */
+@SpringBootApplication
+@ComponentScan(basePackages = "mybatisex")
+@MapperScan(basePackages = "mybatisex.core.service")
+public class TestConfiguration {
+
+	/**
+	 * 配置 MetaObjectHandler,用于自动填充字段
+	 */
+	@Bean
+	public MetaObjectHandler metaObjectHandler() {
+		return new DefaultDBFieldHandler();
+	}
+}

+ 65 - 0
src/test/java/mybatisex/core/service/TestOrderDO.java

@@ -0,0 +1,65 @@
+package mybatisex.core.service;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import mybatisex.core.dataobject.BaseDO;
+
+/**
+ * 测试订单实体类(用于 Service 测试)
+ */
+@TableName("test_order")
+public class TestOrderDO extends BaseDO {
+
+	@TableId(type = IdType.AUTO)
+	private Long id;
+
+	private Long userId;
+
+	private String orderNo;
+
+	private Double amount;
+
+	private String status;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getUserId() {
+		return userId;
+	}
+
+	public void setUserId(Long userId) {
+		this.userId = userId;
+	}
+
+	public String getOrderNo() {
+		return orderNo;
+	}
+
+	public void setOrderNo(String orderNo) {
+		this.orderNo = orderNo;
+	}
+
+	public Double getAmount() {
+		return amount;
+	}
+
+	public void setAmount(Double amount) {
+		this.amount = amount;
+	}
+
+	public String getStatus() {
+		return status;
+	}
+
+	public void setStatus(String status) {
+		this.status = status;
+	}
+}

+ 12 - 0
src/test/java/mybatisex/core/service/TestOrderMapper.java

@@ -0,0 +1,12 @@
+package mybatisex.core.service;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import mybatisex.core.mapper.PlusBaseMapperX;
+
+/**
+ * 测试订单 Mapper 接口
+ */
+@Mapper
+public interface TestOrderMapper extends PlusBaseMapperX<TestOrderDO> {
+}

+ 17 - 0
src/test/java/mybatisex/core/service/TestOrderService.java

@@ -0,0 +1,17 @@
+package mybatisex.core.service;
+
+import org.springframework.stereotype.Service;
+
+import mybatisex.core.service.impl.AbstractServiceImpl;
+
+/**
+ * 测试订单 Service 实现类
+ */
+@Service
+public class TestOrderService extends AbstractServiceImpl<TestOrderMapper, TestOrderDO> implements AbstractService<TestOrderDO> {
+
+	@Override
+	public TestOrderMapper getBaseMapper() {
+		return baseMapper;
+	}
+}

+ 65 - 0
src/test/java/mybatisex/core/service/TestUserDO.java

@@ -0,0 +1,65 @@
+package mybatisex.core.service;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import mybatisex.core.dataobject.BaseDO;
+
+/**
+ * 测试用户实体类(用于 Service 测试)
+ */
+@TableName("test_user")
+public class TestUserDO extends BaseDO {
+
+	@TableId(type = IdType.AUTO)
+	private Long id;
+
+	private String userName;
+
+	private String email;
+
+	private Integer age;
+
+	private String status;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public String getUserName() {
+		return userName;
+	}
+
+	public void setUserName(String userName) {
+		this.userName = userName;
+	}
+
+	public String getEmail() {
+		return email;
+	}
+
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+	public Integer getAge() {
+		return age;
+	}
+
+	public void setAge(Integer age) {
+		this.age = age;
+	}
+
+	public String getStatus() {
+		return status;
+	}
+
+	public void setStatus(String status) {
+		this.status = status;
+	}
+}

+ 12 - 0
src/test/java/mybatisex/core/service/TestUserMapper.java

@@ -0,0 +1,12 @@
+package mybatisex.core.service;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import mybatisex.core.mapper.PlusBaseMapperX;
+
+/**
+ * 测试用户 Mapper 接口
+ */
+@Mapper
+public interface TestUserMapper extends PlusBaseMapperX<TestUserDO> {
+}

+ 17 - 0
src/test/java/mybatisex/core/service/TestUserService.java

@@ -0,0 +1,17 @@
+package mybatisex.core.service;
+
+import org.springframework.stereotype.Service;
+
+import mybatisex.core.service.impl.AbstractServiceImpl;
+
+/**
+ * 测试用户 Service 实现类
+ */
+@Service
+public class TestUserService extends AbstractServiceImpl<TestUserMapper, TestUserDO> implements AbstractService<TestUserDO> {
+
+	@Override
+	public TestUserMapper getBaseMapper() {
+		return baseMapper;
+	}
+}

+ 80 - 0
src/test/java/mybatisex/core/service/UserOrderDTO.java

@@ -0,0 +1,80 @@
+package mybatisex.core.service;
+
+/**
+ * 用户订单 DTO(用于 join 查询结果)
+ */
+public class UserOrderDTO {
+
+	private Long userId;
+	private String userName;
+	private String email;
+	private Integer age;
+	private Long orderId;
+	private String orderNo;
+	private Double amount;
+	private String orderStatus;
+
+	public Long getUserId() {
+		return userId;
+	}
+
+	public void setUserId(Long userId) {
+		this.userId = userId;
+	}
+
+	public String getUserName() {
+		return userName;
+	}
+
+	public void setUserName(String userName) {
+		this.userName = userName;
+	}
+
+	public String getEmail() {
+		return email;
+	}
+
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+	public Integer getAge() {
+		return age;
+	}
+
+	public void setAge(Integer age) {
+		this.age = age;
+	}
+
+	public Long getOrderId() {
+		return orderId;
+	}
+
+	public void setOrderId(Long orderId) {
+		this.orderId = orderId;
+	}
+
+	public String getOrderNo() {
+		return orderNo;
+	}
+
+	public void setOrderNo(String orderNo) {
+		this.orderNo = orderNo;
+	}
+
+	public Double getAmount() {
+		return amount;
+	}
+
+	public void setAmount(Double amount) {
+		this.amount = amount;
+	}
+
+	public String getOrderStatus() {
+		return orderStatus;
+	}
+
+	public void setOrderStatus(String orderStatus) {
+		this.orderStatus = orderStatus;
+	}
+}

+ 24 - 0
src/test/resources/application.yml

@@ -0,0 +1,24 @@
+spring:
+  datasource:
+    driver-class-name: org.h2.Driver
+    url: jdbc:h2:mem:testdb;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH;INIT=CREATE SCHEMA IF NOT EXISTS PUBLIC\\;RUNSCRIPT FROM 'classpath:schema.sql'
+    username: sa
+    password: 
+    hikari:
+      maximum-pool-size: 5
+      minimum-idle: 1
+  sql:
+    init:
+      mode: always
+      schema-locations: classpath:schema.sql
+
+mybatis-plus:
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  global-config:
+    db-config:
+      id-type: auto
+      logic-delete-field: deleted
+      logic-delete-value: 1
+      logic-not-delete-value: 0

+ 27 - 0
src/test/resources/schema.sql

@@ -0,0 +1,27 @@
+-- H2 数据库表结构初始化脚本
+
+CREATE TABLE IF NOT EXISTS test_user (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    user_name VARCHAR(100),
+    email VARCHAR(100),
+    age INT,
+    status VARCHAR(50),
+    create_time TIMESTAMP,
+    update_time TIMESTAMP,
+    creator VARCHAR(100),
+    updater VARCHAR(100),
+    deleted BOOLEAN DEFAULT FALSE
+);
+
+CREATE TABLE IF NOT EXISTS test_order (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    user_id BIGINT,
+    order_no VARCHAR(100),
+    amount DECIMAL(10, 2),
+    status VARCHAR(50),
+    create_time TIMESTAMP,
+    update_time TIMESTAMP,
+    creator VARCHAR(100),
+    updater VARCHAR(100),
+    deleted BOOLEAN DEFAULT FALSE
+);