文章目录
前言
使用了mybatis-plus在单表查询上几乎不用自己手动编写sql,但是在条件过多的情况下填充较为麻烦
一、mybatis-plus传统的查询方式
1.1 使用QueryWrapper查询
@Test
void contextLoads() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username","zhangsan");
System.out.println(userInfoMapper.selectList(queryWrapper));
}
- 缺点:直接将字段名写在查询条件上,硬编码,易出错
1.2 使用LambdaQueryWrapper查询
@Test
void contextLoads() {
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserInfo::getUsername,"zhangsan");
System.out.println(userInfoMapper.selectList(queryWrapper));
}
-
优点:使用lambda表达式,解决硬编码问题。
-
缺点:在条件过多时需要一个个判断,一个个填充
二、查询优化
2.1 相同的方法
- 通过查看源代码,发现QueryWrapper与LambdaQueryWrapper都继承AbstractWrapper,选出这个类的参数类型与参数个数相同的方法。(其中in与notIn也很常用,但是第三个参数类型不一致,所以后面做了兼容处理)
2.2 优化实现
-
方法名枚举类
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; import java.lang.reflect.Method; /** * @author lyk */ public enum QueryConditionEnum { EQ("eq"), NE("ne"), GT("gt"), GE("ge"), LT("lt"), LE("le"), LIKE("like"), NOT_LIKE("notLike"), LIKE_LEFT("likeLeft"), LIKE_RIGHT("likeRight"), // in 与 notIn应加在列表上,若From字段名称与数据库对不上应加@TableField并指出对应的数据库字段名 IN("in"), NOT_IN("notIn"); private String name; private Method method; QueryConditionEnum (String name) { this.name = name; try { Method method = null; if ("in".equals(name) || "notIn".equals(name)) { method = AbstractWrapper.class.getDeclaredMethod(name, boolean.class, Object.class, Collection.class); } else { method = AbstractWrapper.class.getDeclaredMethod(name, boolean.class, Object.class, Object.class); } this.method = method; } catch (NoSuchMethodException e) { } } public Method getMethod() { return method; } }
-
自定义条件注解(用于查询的字段上,如若不填默认为eq)
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author lyk */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface QueryCondition { /** * 默认查询方式 * * @return */ QueryConditionEnum value() default QueryConditionEnum.EQ; /** * 是否填充默认查询条件 * * @return */ boolean isCondition() default true; }
-
默认填充工具类
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * mybatis-plus 条件构造器 * * @author lyk */ public class QueryUtil { /** * 填充默认查询 * * @param baseClazz mo对象class * @param queryWrapper 查询条件 * @param form 请求对象 */ public static void paddingDefaultConditionQuery(Class baseClazz, QueryWrapper queryWrapper, Object form) { try { for (Field declaredField : form.getClass().getDeclaredFields()) { declaredField.setAccessible(true); Object fieldValue = declaredField.get(form); QueryCondition queryCondition = declaredField.getAnnotation(QueryCondition.class); // 若值为空则不填充 if (fieldValue == null) { continue; } // 若没加 QueryCondition 注解则认为是eq if (queryCondition == null) { // 填充条件 queryWrapper.eq(StringUtils.isNotBlank(fieldValue.toString()), QueryUtil.getTableFieldName(baseClazz, declaredField), fieldValue.toString()); continue; } // 若注解标识为不填充 则跳过 if (queryCondition.isCondition() == false) { continue; } // 枚举类通过反射获取到 相应的方法,并填充条件 Method method = queryCondition.value().getMethod(); method.invoke(queryWrapper, ObjectUtils.isNotEmpty(fieldValue.toString()), QueryUtil.getTableFieldName(baseClazz, declaredField), fieldValue.toString()); } } catch (Exception e) { throw new RuntimeException("填充默认的SQL条件出错", e); } } /** * 获取字段名 * 若from的字段名称跟实体类字段名称对应上则取实体类上 TableId、TableField上的值,若没加这两个注解则取字段名称 * 若from的字段名称跟实体类字段名称对应不上则取From类 TableId、TableField上的值,若没加这两个注解则取字段名称 * * @param field * @return */ public static String getTableFieldName(Class baseClazz, Field field) { Field baseField = null; try { baseField = baseClazz.getDeclaredField(field.getName()); } catch (NoSuchFieldException e) { e.printStackTrace(); } if (baseField == null) { baseField = field; } TableId tableId = baseField.getAnnotation(TableId.class); if (tableId != null && StringUtils.isNotBlank(tableId.value())) { return tableId.value(); } TableField tableField = baseField.getAnnotation(TableField.class); if (tableField != null && StringUtils.isNotBlank(tableField.value())) { return tableField.value(); } // 若数据库字段名称使用的命名方式为驼峰 则 return baseField.getName(); return StringUtils.camelToUnderline(baseField.getName()); } }
2.3 调用
-
条件From
import com.ivan.mpdemo.util.QueryCondition; import com.ivan.mpdemo.util.QueryConditionEnum; import lombok.Data; /** * @author lyk */ @Data public class UserForm { @QueryCondition(QueryConditionEnum.LIKE) private String username; private String nickname; }
-
查询方法
@Autowired private UserInfoMapper userInfoMapper; @Test void contextLoads() { UserForm userForm = new UserForm(); userForm.setUsername("b"); userForm.setNickname("bbb"); QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>(); QueryUtil.paddingDefaultConditionQuery(UserInfo.class,queryWrapper,userForm); System.out.println(userInfoMapper.selectList(queryWrapper)); }
-
结果