MyBatis中不建议使用where 1=1原因详解

作者:Java中文社群 时间:2021-08-09 23:25:55 

前言

最近接手了一个老项目,“愉悦的心情”自然无以言表,做开发的朋友都懂,这里就不多说了,都是泪...

接手老项目,自然是要先熟悉一下业务代码,然而在翻阅 mapper 文件时,发现了一个比较诡异的事情。这里给出简化后的业务代码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
   <select id="list" resultType="com.example.demo.model.User">
       select * from user
       where 1=1
       <if test="name!=null">
           and name=#{name}
       </if>
       <if test="password!=null">
           and password=#{password}
       </if>
   </select>
</mapper>

机智的小伙伴可能已经看出了问题,在众多 mapper 中发现了一个相同的想象,几乎所有的 mapper 中都包含了一个无用的拼接 SQL:where 1=1。作为一个几乎有代码洁癖症的人,自然是忍不住动手改造一番了。

错误的改造方式

既然是去掉 where 1=1,那最简单的方式就是将它直接从代码中删除了,如下代码所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
   <select id="list" resultType="com.example.demo.model.User">
       select * from user
           where
           <if test="name!=null">
               name=#{name}
           </if>
           <if test="password!=null">
               and password=#{password}
           </if>
   </select>
</mapper>

以上代码删除了 1=1,并且把第一个 name 查询中的 and 去掉了,以防 SQL 查询报错。

但这样就没问题了吗?我们直接来看结果,当包含参数 name 查询时,结果如下:

MyBatis中不建议使用where 1=1原因详解

一切顺利成章,完美的一塌糊涂。

然而,当省略 name 参数时(因为 name 为非必要参数,所以可以省略),竟然引发了以下异常:

MyBatis中不建议使用where 1=1原因详解

又或者只有 password 查询时,结果也是一样:

MyBatis中不建议使用where 1=1原因详解

都是报错信息,那肿么办呢?难不成把 1=1 恢复回去?

正确的改进方式

其实不用,在 MyBatis 中早已经想到了这个问题,我们可以将 SQL 中的 where 关键字换成 MyBatis 中的 标签,并且给每个 标签内都加上 and 拼接符,这样问题就解决了,如下代码所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
   <select id="list" resultType="com.example.demo.model.User">
       select * from user
       <where>
           <if test="name!=null">
              and name=#{name}
           </if>
           <if test="password!=null">
               and password=#{password}
           </if>
       </where>
   </select>
</mapper>

代码改造完成之后,接下来我们来测试一下所有的请求场景。

不传任何参数的请求

此时我们可以不传递任何参数(查询所有数据),如下图所示:

MyBatis中不建议使用where 1=1原因详解

生成的 SQL 语句如下:

MyBatis中不建议使用where 1=1原因详解

传递 1 个参数的请求

也可以传递 1 个参数,根据 name 进行查询,如下图所示:

MyBatis中不建议使用where 1=1原因详解

生成的 SQL 如下图所示:

MyBatis中不建议使用where 1=1原因详解

也可以只根据 password 进行查询,如下图所示:

MyBatis中不建议使用where 1=1原因详解

生成的 SQL 如下图所示:

MyBatis中不建议使用where 1=1原因详解

传递 2 个参数的请求

也可以根据 name 加 password 的方式进行联合查询,如下图所示:

MyBatis中不建议使用where 1=1原因详解

生成的 SQL 如下图所示:

MyBatis中不建议使用where 1=1原因详解

用法解析

我们惊喜的发现,在使用了 标签之后,无论是任何查询场景,传一个或者传多个参数,或者直接不传递任何参数,都可以轻松搞定。

首先, 标签会判断,如果没有任何参数,则不会在 SQL 语句中拼接 where 查询,反之才会拼接 where 查询;其次在 查询的 标签中,每个 标签都可以加 and 关键字,MyBatis 会自动将第一个条件前面的 and 关键字删除掉,从而不会导致 SQL 语法错误,这一点官方文档中也有说明,如下图所示:

来源:https://juejin.cn/post/7030414603699879972

标签:MyBatis,where1=1
0
投稿

猜你喜欢

  • Java String类简单用法实战示例【字符串输出、比较】

    2021-09-22 11:59:51
  • Mybatis-Plus注入SQL原理分析

    2022-11-09 21:17:22
  • 关于Lambda表达式的方法引用和构造器引用简的单示例

    2022-09-18 05:02:08
  • Java自动添加重写的toString方法详解

    2021-11-05 14:29:13
  • SpringBoot中打war包需要注意事项

    2023-11-05 19:44:42
  • 你真的知道Java中对象的销毁吗

    2022-09-14 22:31:38
  • Java设计模式--代理模式

    2023-02-26 21:45:32
  • springboot集成mybatisPlus+多数据源的实现示例

    2023-11-24 22:35:02
  • C#日期格式强制转换方法(推荐)

    2022-09-19 10:24:57
  • Spring Boot + Mybatis多数据源和动态数据源配置方法

    2023-02-16 17:15:31
  • JAVA中 redisTemplate 和 jedis的配合使用操作

    2022-05-01 23:38:46
  • Android仿百度图片查看功能

    2023-09-26 07:50:24
  • 详解使用Spring Security OAuth 实现OAuth 2.0 授权

    2023-10-01 23:05:10
  • Spring Boot 详细分析Conditional自动化配置注解

    2021-11-25 21:56:14
  • C# linq查询之动态OrderBy用法实例

    2023-11-04 04:22:56
  • java获取文件的inode标识符的方法

    2021-06-19 15:10:49
  • JAVA读取文件夹大小的几种方法实例

    2021-05-24 21:01:53
  • Java面试题冲刺第二十五天--并发编程3

    2023-09-11 04:40:10
  • redis redisson 集合的使用案例(RList、Rset、RMap)

    2023-11-13 13:50:21
  • SpringBoot在IDEA中实现热部署的步骤

    2022-01-14 23:30:02
  • asp之家 软件编程 m.aspxhome.com