关于mybatis plus 中的查询优化问题

传统的mybatis plus 查询写法

对于常规的mybatis单表查询,我们既可以采用LambdaQueryWrapper查询,也可以使用QueryWrapper查询。
LambdaQueryWrapper具有防误写、规范代码等好处,但是缺点是无法在复杂的多表查询中使用。
相比较来说,使用QueryWrapper编写查询更加灵活,可以适应更复杂的查询场景。
我们首先看一个QueryWrapper查询的例子

public List<UserMo> list (UserForm userForm) {
 QueryWrapper<UserMo> queryWrapper = new QueryWrapper<>();
 queryWrapper.like(StringTool.isNotEmpty(userForm.getUserName(), "name", userForm.getUserName());
 queryWrapper.eq(StringTool.isNotEmpty(userForm.getMobile(), "mobile", userForm.getMobile());
 // 其它的查询条件...
 return userMapper.selectList(queryWrapper);
}

对于上面的查询语句来说,可以很好的对前端传值进行处理,当userForm中有前端传值的话,就会往SQL语句中加一条where条件。
但是这样做的话会有一个相对来说比较复杂的点,那就是当UserForm中的字段过于多的时候,我们也许得写十几行的这种重复判断的语句。

通过自定义注解来解决通用查询条件过多问题

通过观察mybatis plus 对于queryWrapper相关查询方法的列子,我们可以找出一类通用方法

可以看出来这几个方法都是传的同样的三个参数。
我想对于这些简单的通用的查询条件,也许可以有一个通用的方法来填充。
我首先设置了一个枚举类,将这些查询条件列出来,并在构造方法中,将对应的方法以反射的方式取到。

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");

 private String name;

 private Method method;

 QueryConditionEnum (String name) {
  this.name = name;
  try {
   Method method = AbstractWrapper.class.getDeclaredMethod(name, boolean.class, Object.class, Object.class);
   this.method = method;
  } catch (NoSuchMethodException e) {
  }
 }

}

再者,我想通过注解的方式来规定需要以什么方法填充,默认为EQ,对此写了一个QueryCondition注解。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface QueryCondition {

 /**
  * 默认查询方式
  *
  * @return
  */
 QueryConditionEnum value() default QueryConditionEnum.EQ;

 /**
  * 是否填充默认查询条件
  *
  * @return
  */
 boolean isCondition() default true;

}

然后就可以这样构造UserForm

public class UserForm {
 private String name;

 @QueryCondition(QueryConditionEnum.LIKE)
 private String mobile;
}

我们需要一个工具类填充查询条件,这里我们新增了一个参数 mo对象,这是因为我们的主查询对象是Mo对象,Mo对象存储了相关表格名称、表格字段名信息。

@TableName("user")
public class UserMo {
 @TableField("name")
 private String name;

 @TableField("mobile")
 private String mobile;
}
public class QueryTool {

 /**
  * 填充默认查询
  * @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;
    }
    if (queryCondition == null) {
     queryWrapper.eq(StringTool.isNotEmpty(fieldValue.toString()),
      QueryTool.getTableName(baseClazz) + "." + QueryTool.getTableFieldName(baseClazz, declaredField),
      fieldValue.toString());
     continue;
    }
    if (queryCondition.isCondition() == false) {
     continue;
    }
    Method method = queryCondition.value().getMethod();
    method.invoke(queryWrapper, StringTool.isNotEmpty(fieldValue.toString()),
     QueryTool.getTableName(baseClazz) + "." + QueryTool.getTableFieldName(baseClazz, declaredField),
     fieldValue.toString());
   }
  } catch (Exception e) {
   throw new RuntimeException("填充默认的SQL条件出错", e);
  }
 }

 /**
  * 填充默认排序
  *
  * @param queryWrapper
  * @param pageForm
  */
 public static void paddingDefaultOrderQuery(QueryWrapper queryWrapper, PageForm pageForm) {
  queryWrapper.orderBy(pageForm != null && StringTool.isNotEmpty(pageForm.getColumnName()),
   pageForm.getIsAsc() == null ? false : pageForm.getIsAsc(), pageForm.getColumnName());
 }

 /**
  * 获取表名称
  *
  * @return
  */
 public static String getTableName(Class baseClazz) {
  TableName tableName = (TableName) baseClazz.getDeclaredAnnotation(TableName.class);
  if (tableName != null && StringTool.isNotEmpty(tableName.value())) {
   return tableName.value();
  }
  return StringTool.toUnderline(baseClazz.getClass().getName());
 }

 /**
  * 获取字段名
  *
  * @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 && StringTool.isNotEmpty(tableId.value())) {
   return tableId.value();
  }
  TableField tableField = baseField.getAnnotation(TableField.class);
  if (tableField != null && StringTool.isNotEmpty(tableField.value())) {
   return tableField.value();
  }
  return StringTool.toUnderline(baseField.getName());
 }

}

最后我们就可以使用工具类来填充了 。

public List<UserMo> list (UserForm userForm) {
 QueryWrapper<UserMo> queryWrapper = new QueryWrapper<>();
 QueryTool.paddingDefaultConditionQuery(UserMo.class, queryWrapper, userForm);
 return userMapper.selectList(queryWrapper);
}

可以看到这样大大减少了需要填充的字段。如果有特殊字段,也能通过注解方式,跳过特殊字段,再自行填充就好。

到此这篇关于关于mybatis plus 中的查询优化的文章就介绍到这了,更多相关mybatis plus 查询优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mybatis-plus分页查询的实现示例

    按照官方文档进行的配置:快速开始|mybatis-plus 引入依赖: <!-- 引入mybatisPlus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--

  • MyBatis-Plus 如何实现连表查询的示例代码

    在项目开发中,难免会遇到连表查询的操作. 项目中用的是 MyBatis-Plus,是新使用的框架.官方文档看这里. 我写过一篇通过单元测试来验证 MyBatis-Plus 的 CRUD 操作.点这里跳转 今天遇到连表查询的问题,特此记录一下. 遇到需要连表操作,想起 MyBatis 的操作连表查询,要是 MyBatis-Plus 也像 MyBatis 一样,就脑壳痛了.(MyBatis-Plus 是 MyBatis 的增强版) 脑壳痛归脑壳痛,先动手干. 首先 因为官方的内置接口方法都是针对单表

  • mybatis-plus QueryWrapper自定义查询条件的实现

    mybatis-plus框架功能很强大,把很多功能都集成了,比如自动生成代码结构,mybatis crud封装,分页,动态数据源等等,附上官网链接https://mp.baomidou.com/,github上有代码例子,国内小伙伴推荐码云https://gitee.com/baomidou/mybatis-plus.  但是,其中还是有些小坑,文档也没有涉及的很全面,碰到问题,百度或者发issue,能力强的还是直接看源码好,一切答案都在源码中. 版本推荐用3.1.0,3.1.1及以上版本有bu

  • 完美解决MybatisPlus插件分页查询不起作用总是查询全部数据问题

    问题描述: 在使用mybatisplus插件进行分页查询时分页参数不起作用,总是查出来全部数据. 原因分析: 查看打印的sql日志发现sql后面并没有limit条件,怀疑是缺少配置. 解决方案: 查阅资料通过添加配置类MybatisPlusConfig解决问题: @Configuration public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor(){ return new

  • 结合mybatis-plus实现简单不需要写sql的多表查询

    项目地址: GITHUB (本地下载) java mybatis 多表查询 简介 实现简单的实体类操作多表,  首先你的项目是使用了mybatis-plus 才可以使用 设计说明 如何关联表? 找第一张表注解为 TableId (mybatis-plus 注解)的属性名, 到每二张表找同样的属性名, 如果没找到,反过来找,如果还没找到,挨个属性找.以此类推,实现关联的前提条件是 主从表的关联例名必须一样 // user 表 @TableId private Integer userId // a

  • MyBatis-plus 模糊查询的使用

    在使用MyBatis-plus的时候,一些基础的增删改查可以不用再自己写sql了: public interface UserDao extends BaseMapper<FykUser>{ } 就这样,就可以实现user表的增删改查了. 模糊查询 使用userDao.selectList(queryWrapper)方法,就可以查询出一个用户列表. 如果需要模糊查询,代码如下: //条件封装 QueryWrapper<FykUser> queryWrapper = new Quer

  • 关于mybatis plus 中的查询优化问题

    传统的mybatis plus 查询写法 对于常规的mybatis单表查询,我们既可以采用LambdaQueryWrapper查询,也可以使用QueryWrapper查询. LambdaQueryWrapper具有防误写.规范代码等好处,但是缺点是无法在复杂的多表查询中使用. 相比较来说,使用QueryWrapper编写查询更加灵活,可以适应更复杂的查询场景. 我们首先看一个QueryWrapper查询的例子 public List<UserMo> list (UserForm userFor

  • 整理Java的MyBatis框架中一些重要的功能及基本使用示例

    基本用法回顾: SQL语句存储在XML文件或Java 注解中.一个MaBatis映射的示例(其中用到了Java接口和MyBatis注解): package org.mybatis.example; public interface BlogMapper { @Select("select * from Blog where id = #{id}") Blog selectBlog(int id); } 执行的示例: BlogMapper mapper = session.getMapp

  • Java的MyBatis框架中XML映射缓存的使用教程

    MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.默认情况下是没有开启缓存的,要开启二级缓存,你需要在你的SQL映射文件中添加一行: <cache/> 字面上看就是这样.这个简单语句的效果如下: 1.映射语句文件中的所有select语句将会被缓存. 2.映射语句文件中的所有insert,update和delete语句会刷新缓存. 3.缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回. 4.根据时间表(比如 no Flush Inter

  • MyBatis框架中mybatis配置文件详细介绍

    一.注册DB连接四要素属性文件 <propertiesresource="jdbc.properties"/> 二.将指定包中所有类的简单类名当作其别名 <typeAliases> <packagename="com.bjpowernode.beans"/> </typeAliases> 三.配置运行环境 <environmentsdefault="testEM"> <enviro

  • mybatis xml中特殊字符处理及特殊符号

    下面给大家介绍mybatis xml 中特殊字符处理方法,具体内容如下所示:  1,CDATA区: 它的全称为character data,以"<![CDATA[ "开始,以" ]]>" 结束,在两者之间嵌入不想被解析程序解析的原始数据,解析器不对CDATA区中的内容进行解析,而是将这些数据原封不动地交给下游程序处理. 2,特殊字符 : xml 中表示:   <= 小于等于.    >= 大于等于 需加  这样的标记:     <![C

  • 优化MyBatis配置文件中的配置详解

    本文研究的主要是优化MyBatis配置文件中的配置的相关内容,具体介绍如下. 一.连接数据库的配置单独放在一个properties文件中 之前,我们是直接将数据库的连接配置信息写在了MyBatis的conf.xml文件中,如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN&

  • Mybatis plus中使用in查询出错如何解决

    不想看我bb的直接点上面的 ''解决方法'' 我的情况是这样的,在使用mybatis plus提供的QueryWrapper方法里的in查询时,我的参数为类似"1,2,3,4"这样的字符串 //要查的参数 String masterIds = "81554,5654,55948,48945"; QueryWrapper<FpjyPauperInfo> pauperqw = new QueryWrapper<>(); pauperqw.in(&

  • MyBatis Plus中代码生成器使用详解

    按照官网上实例尝试了一下,感觉MyBatis plus中代码生成器还是很强大的,以下是测试的总结: 使用MybatisPlus的主要依赖 引入plus依赖(苞米豆) <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </depe

  • 关于MyBatis Plus中使用or和and问题

    最近在使用MyBatis Plus,发现在拼接条件的时候,and和or会出问题,比如下面这种 QueryWrapper userWrapper = new QueryWrapper(); userWrapper.eq("name", name); userWrapper.eq("pwd", pwd).or().eq("phone", phone); 这种写法拼出来的SQL语句是这样的: select * from user where (name

  • mybatis+springboot中使用mysql的实例

    目录 依赖引入 配置引入 案例实现 案例源码 在软件开发中,数据库的引入是必不可少的,其中又属mysql使用最为广泛,而在springboot中,集成使用mysql的方式有很多(例如jpa),这里来展现一下通过mybatis框架在springboot中使用mysql. 依赖引入 首先在使用初始化工程的时候加入mybatis.mysql相关的依赖,如下所示: <dependencies> <dependency> <groupId>org.springframework.

随机推荐