MyBatis动态SQL

MyBatis能够在Mapper配置XML文件中,使用<if><choose>等标签动态拼接SQL语句。实际上,动态拼接SQL不代表我们把软件的业务逻辑搬到了配置文件中,这个功能只是为了让SQL能更好的完成每一个持久层的数据操作任务,因此动态SQL一般有固定的几个应用场景,比如动态查询。XML配置文件中拼接SQL可读性极差,而且完全无法debug,因此不要滥用这个功能。

下面我们简单介绍Mybatis的动态SQL标签用法。

例子表结构

例子使用的数据库表和Java实体类如下。

create table t_user(
    user_id bigint auto_increment,
    username varchar(255) not null,
    email varchar(255) not null,
    password varchar(255) not null,
    primary key(user_id)
);
@Data
public class User {
    private Long userId;
    private String username;
    private String email;
    private String password;
}

if

下面例子中,实现的功能是根据多个字段的模糊匹配查询。

public List<User> searchUserByUsernameAndEmail(@Param("username") String username, @Param("email") String email);
<select id="searchUserByUsernameAndEmail" resultType="com.gacfox.demomb.model.User">
  select user_id as userId,username,email,password from t_user
  where 1=1
  <if test="username != null and username != ''">
    and username like concat('%',#{username},'%')
  </if>
  <if test="email != null and email != ''">
    and email like concat('%',#{email},'%')
  </if>
</select>

<if>标签必须有test属性,其中的内容实际上是OGNL表达式(在struts2章节介绍过),根据表达式结果是truefalse判断该分支是否拼接到SQL上。

注意:where 1=1,因为每个匹配条件都是and开头的,这是为了拼接后的SQL不至于语法出错,这不是最好的写法,推荐使用where标签(后文会介绍)。

choose

if只能实现一个分支判断,choose可以实现多个。

<choose>
  <when test=""></when>
  <otherwise></otherwise>
</choose>

注意:

  • iftest属性一样,whentest也是OGNL表达式
  • when标签可以写多个

where

这里再次使用if的例子,将其使用where进行改进。

<select id="searchUserByUsernameAndEmail" resultType="com.gacfox.demomb.model.User">
  select user_id as userId,username,email,password from t_user
  <where>
    <if test="username != null and username != ''">
      and username like concat('%',#{username},'%')
    </if>
    <if test="email != null and email != ''">
      and email like concat('%',#{email},'%')
    </if>
  </where>
</select>

<where>的作用:where内部包裹的元素有返回值时,在SQL中加上一个WHERE,否则不加;如果内部包裹的元素以ANDOR开头,将其去掉。总之,where就是配合动态拼接SQL条件子句使用的。

set

这个标签类比where标签理解即可:如果set包裹的元素有返回值时,就插入一个set;如果内部包裹元素最后以逗号,结尾,将其去掉。

这个标签是配合UPDATE语句使用的。

trim

实际上面介绍的whereset标签都可以用trim标签实现,trim是一个更加通用的用于辅助动态拼接SQL的标签:

trim实现set标签。

<trim prefix="SET" suffixOverrides=","></trim>
  • prefixtrim内部包含内容时,会加上前缀
  • prefixOverridestrim内部包含内容时,会去掉该前缀
  • suffixtrim内部包含内容时,会加上后缀
  • suffixOverridestrim内部包含内容时,会去掉该后缀

foreach

该标签用于对实现了Iterable接口的Java对象进行遍历,分为ListMap两种情况,下面举两个例子。

生成一个IN子句的范围:

<foreach collection="idList" open="(" close= ")" separator= "," item="id" index="i">
  #{id}
</foreach>
  • collection:要迭代的属性名
  • open:整个的前缀
  • close:整个的后缀
  • separator:分隔符
  • item:迭代的变量名
  • indexList是当前的索引值,Map是当前的键值

bind

bind标签用于创建一个值并绑定到一个变量上,比较少用。

<bind name="" value="" />
  • name:创建的变量名
  • value:创建的变量值
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap