Mybatis的where标签使用总结梳理

目录
  • 背景
  • 原始的手动拼接
  • Mybatis where标签的使用
  • 进阶:自定义trim标签
  • where语句的坑
  • 小结

背景

在上篇文章,我们系统地学习了where 1=1 相关的知识点,大家可以回看《MySQL中where 1=1方法的使用及改进》这篇文章。文章中涉及到了Mybatis的替代方案,有好学的朋友在评论区有朋友问了基于Mybatis写法的问题。

本篇文章会将Mybatis中where标签的基本使用形式、小技巧以及容易踩到的坑进行总结梳理,方便大家更好地实践运用d

原始的手动拼接

在不使用Mybatis的where标签时,我们通常是根据查询条件进行手动拼接,也就是用到了上面提到的where 1=1的方式,示例如下:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    where 1=1
    <if test="username != null and username != ''">
     and username = #{username}
    </if>
    <if test="idNo != null and idNo != ''">
      and id_no = #{idNo}
    </if>
  </select>

这种方式主要就是为了避免语句拼接错误,出现类似如下的错误SQL:

select * from t_user where and username = 'Tom' and id = '1001';
select * from t_user where and id = '1001';

当添加上1=1时,SQL语句便是正确的了:

select * from t_user where 1=1 and username = 'Tom' and id = '1001';
select * from t_user where 1=1 and id = '1001';

这个我们之前已经提到过,多少对MySQL数据库的有一定的压力。因为1=1条件的优化过滤是需要MySQL做的。如果能够将这部分放到应用程序来做,就减少了MySQL的压力。毕竟,应用程序是可以轻易地横向扩展的。

Mybatis where标签的使用

为了能达到MySQL性能的调优,我们可以基于Mybatis的where标签来进行实现。where标签是顶层的遍历标签,需要配合if标签使用,单独使用无意义。通常有下面两种实现形式。

方式一:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <where>
      <if test="username != null and username != ''">
        username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        and id_no = #{idNo}
      </if>
    </where>
  </select>

方式二:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <where>
      <if test="username != null and username != ''">
        and username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        and id_no = #{idNo}
      </if>
    </where>
  </select>

仔细观察会发现,这两种方式的区别在于第一if条件中的SQL语句是否有and

这里就涉及到where标签的两个特性:

  • 第一,只有if标签有内容的情况下才会插入where子句;
  • 第二,若子句的开通为 “AND” 或 “OR”,where标签会将它替换去除;

所以说,上面的两种写法都是可以了,Mybatis的where标签会替我们做一些事情。

但需要注意的是:where标签只会 智能的去除(忽略)首个满足条件语句的前缀。所以建议在使用where标签时,每个语句都最好写上 and 前缀或者 or 前缀,否则像以下写法就会出现问题:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <where>
      <if test="username != null and username != ''">
        username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        id_no = #{idNo}
      </if>
    </where>
  </select>

生成的SQL语句如下:

select * from t_user      WHERE username = ?  id_no = ?

很显然,语法是错误的。

因此,在使用where标签时,建议将所有条件都添加上and或or

进阶:自定义trim标签

上面使用where标签可以达到拼接条件语句时,自动去掉首个条件的and或or,那么如果是其他自定义的关键字是否也能去掉呢?

此时,where标签就无能为力了,该trim标签上场了,它也可以实现where标签的功能。

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <trim prefix="where" prefixOverrides="and | or ">
      <if test="username != null and username != ''">
        and username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        and id_no = #{idNo}
      </if>
    </trim>
  </select>

将上面基于where标签的写改写为trim标签,发现执行效果完全一样。而且trim标签具有了更加灵活的自定义性。

where语句的坑

另外,在使用where语句或其他语句时一定要注意一个地方,那就是:注释的使用。

先来看例子:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <where>
      <if test="username != null and username != ''">
        and username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        /* and id_no = #{idNo}*/
        and id_no = #{idNo}
      </if>
    </where>
  </select>

上述SQL语句中添加了 /**/的注释,生成的SQL语句为:

select * from t_user WHERE username = ? /* and id_no = ?*/ and id_no = ?

执行时,直接报错。

还有一个示例:

  <select id="selectSelective" resultType="com.secbro.entity.User">
    select * from t_user
    <where>
      <if test="username != null and username != ''">
        -- and username = #{username}
        and username = #{username}
      </if>
      <if test="idNo != null and idNo != ''">
        and id_no = #{idNo}
      </if>
    </where>
  </select>

生成的SQL语句为:

select * from t_user WHERE -- and username = ? and username = ? and id_no = ? 

同样会导致报错。

这是因为我们使用 XML 方式配置 SQL 时,如果在 where 标签之后添加了注释,那么当有子元素满足条件时,除了 < !-- --> 注释会被 where 忽略解析以外,其它注释例如 // 或 /**/ 或 -- 等都会被 where 当成首个子句元素处理,导致后续真正的首个 AND 子句元素或 OR 子句元素没能被成功替换掉前缀,从而引起语法错误。

同时,个人在实践中也经常发现因为在XML中使用注释不当导致SQL语法错误或执行出错误的结果。强烈建议,非必要,不要在XML中注释掉SQL,可以通过版本管理工具来追溯历史记录和修改。

小结

本文基于Mybatis中where标签的使用,展开讲了它的使用方式、特性以及拓展到trim标签的替代作用,同时,也提到了在使用时可能会出现的坑。内容虽然简单,但如果能够很好地实践、避免踩坑也是能力的体现。

到此这篇关于Mybatis的where标签使用总结梳理的文章就介绍到这了,更多相关Mybatis的where标签 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决mybatis where-if中if不能识别大写AND,OR的问题

    mybatis报错: Caused by: org.apache.ibatis.ognl.ParseException: Encountered " "AND "" at line 1 错误代码: <select id="selectAccountList" resultMap="BaseResultMap"> SELECT ct.customer_name customerName,sam.city_code,s

  • mybatisplus where QueryWrapper加括号嵌套查询方式

    目录 where QueryWrapper加括号嵌套查询 mybatisplus查询语句加括号(.or(),.and()) where QueryWrapper加括号嵌套查询 之前的代码是这个样子的: QueryWrapper<RyxyMemberEntity> wrapper = new QueryWrapper<>();     wrapper.eq("phoneNumber", phone);     if (StringUtils.isEmpty(sce

  • mybatis-plus分页传入参数后sql where条件没有limit分页信息操作

    折腾了差不多两个小时,各种方法尝试,后来想想应该是where过滤后的数据量没有达到默认一页规定的数量所以干脆where就不显示limit信息了,试了一下还真是...这作者还真是把程序做的足够智能,可是这个智能也让我白白花掉了两个小时...还是自己太笨了-- 但是奇怪的是,如果我不设置QueryWrapper参数,where后面的分页限制又是可以出来的.百思不得其解作者的想法... 具体看代码: @Override public PageUtils queryPage(Map<String, Ob

  • Mybatis动态SQL之if、choose、where、set、trim、foreach标记实例详解

    动态SQL就是动态的生成SQL. if标记 假设有这样一种需求:查询用户,当用户名不等于"admin"的时候,我们还需要密码为123456. 数据库中的数据为: MyBatisConfig.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  • Mybatis plus where添加括号方式

    目录 Mybatis plus where添加括号 where或and后面的条件用括号括起来 Mybatis plus where添加括号 List<String> list = xxxx; QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.and(wrapper -> {             for(String bm : list) {                 wrapper.like

  • mybatis where 标签使用

    目录 Mybatiswhere标签的使用 进阶:自定义trim标签 where语句的坑 小结 我们经常在动态构造sql时,为防止注入或防止语句不当时会使用where 1=1 <select id="selectGroupByEmployeeNum" resultMap="BaseResultMap" parameterType="com.dao.impl.ZcChatGroup"> select * from zc_chat_grou

  • Mybatis的where标签使用总结梳理

    目录 背景 原始的手动拼接 Mybatis where标签的使用 进阶:自定义trim标签 where语句的坑 小结 背景 在上篇文章,我们系统地学习了where 1=1 相关的知识点,大家可以回看<MySQL中where 1=1方法的使用及改进>这篇文章.文章中涉及到了Mybatis的替代方案,有好学的朋友在评论区有朋友问了基于Mybatis写法的问题. 本篇文章会将Mybatis中where标签的基本使用形式.小技巧以及容易踩到的坑进行总结梳理,方便大家更好地实践运用d 原始的手动拼接 在

  • MyBatis动态SQL标签用法实例详解

    1.动态SQL片段 通过SQL片段达到代码复用 <!-- 动态条件分页查询 --> <sql id="sql_count"> select count(*) </sql> <sql id="sql_select"> select * </sql> <sql id="sql_where"> from icp <dynamic prepend="where&quo

  • mybatis中resultMap 标签的使用教程

    MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statement.手动设置参数.结果集检索等jdbc繁杂的过程代码. MyBatis特点: 1.开源的优秀持久层框架 2.SQL语句与代码分离 3.面向配置的编程 4.良好支持复杂数据映射 5.动态SQL resultMap 标签: 用来描述如何从数据库结果集中来加载对象 (敲黑板!!)主管数据库的字段和实体类属性的匹配,

  • Mybatis中foreach标签带来的空格\换行\回车问题及解决方案

    原因 在自已做的内容中通过获取多个商品Id,以此来获取多个商品详细信息.但数据库返回的商品信息的顺序与原来List中产品的id顺序并不匹配,这就导致了前端页面商品的信息显示混乱,不匹配. 通过网上找到order by排序可以有效解决这个问题,返回与查询时的产品id顺序一致.还有一点,List时有序的 这里先附带上这个sql语句(只能在数据库中成功) select prod_id, prod_name, price, `describe`, prod_date, prod_pic, integra

  • Mybatis中Mapper标签总结大全

    一.标签分类 定义SQL语句 insert delete update select 配置关联关系 collection association 配置java对象属性与查询结果集中列名的对应关系 resultMap 控制动态SQL拼接 foreach if choose 格式化输出 where set trim 定义常量 sql 其他 include 二.标签总结 1. 基础SQL标签 1.1 查询select 标签属性 id 唯一的名称,对应dao中mapper的接口名称 paramterTy

  • mybatis中bind标签和concat的使用说明

    首先,二种方式都可以用来模糊查询,都能预防 SQL 注入.但是在更换数据库情况下,bind标签通用. <if test=" userName != null and userName !=""> and userName like concat('%' ,#{userName},'%') </if> 使用concat函数连接字符串,在mysql中这个函数支持多个参数,但是在oracle中这个函数只支持2个参数,由于不同数据库之间的语法差异,更换数据库,

  • 基于mybatis中<include>标签的作用说明

    MyBatis中sql标签定义SQL片段,include标签引用,可以复用SQL片段 sql标签中id属性对应include标签中的refid属性.通过include标签将sql片段和原sql片段进行拼接成一个完整的sql语句进行执行. <sql id="sqlid"> res_type_id,res_type </sql> <select id="selectbyId" resultType="com.property.vo

  • MyBatis动态SQL标签的用法详解

    1.MyBatis动态SQL MyBatis 的强大特性之一便是它的动态 SQL,即拼接SQL字符串.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号.利用动态 SQL 这一特性可以彻底摆脱这种痛苦. 通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中. 动态 SQL 元素和

  • MyBatis resultMap id标签的错误使用方式

    目录 MyBatis resultMap id标签的错误使用 本节的问题主要是我对mybatis id标签的错误使用 resultMap标签的使用规则 自定义结果映射规则 association联合查询 使用association进行分布查询 collection分步查询 MyBatis resultMap id标签的错误使用 我们在编写VO对象,如果业务场景稍微复杂一点,就会用到集合属性.例如用户查看个人订单列表,每个订单又包含多种或者多个规格的商品. 本节的问题主要是我对mybatis id

  • MyBatis中foreach标签的collection属性的取值方式

    目录 foreach标签的collection属性的取值 传的是List列表 传的是Array数组 传的是Map collection属性总结 MyBatis使用foreach标签报错 原因 解决方案 foreach标签的collection属性的取值 传的是List列表 接口代码 List<Emp> findEmpByDeptnos(List<Integer> deptnos); xml配置代码 <select id="findEmpByDeptnos"

随机推荐