Mybatis中的动态SQL在xml中支持的几种常用标签

mybatis3之后,采用了功能强大的OGNL表达式语言消除了许多其它繁琐的标签,现在动态SQL在xml中支持的几种标签:

  • if
  • choose(when、otherwise)
  • trim(where、set)
  • foreach
  • bind

 一.if标签

if标签通常用于where语句中,通过判断参数值来决定是否使用某个查询条件,它也经常用于UPDATE语句中判断是否更新某一个字段,还可以再INSERT语句中用来判断是否插入某个字段的值。

1.1 在where条件中使用if

用法:含义就是当if满足时,就执行标签体中的内容。

需求:准备如下数据表,当只输入用户名的时候,就根据这个用户名进行模糊查询匹配的用户;当只输入邮箱时,就根据邮箱完全匹配用户胡;当两者都同时输入时,就需要用这两个条件去查询匹配的用户。

表格:

 

贴下关键代码:

 

 (1)controller

@PostMapping("/selectByUser")
    public List<SysUser> selectByUser(){
        SysUser sysUser=new SysUser();
        sysUser.setUserName("tes");
        return userService.selectByUser(sysUser);
    }

说明:这里只传入了userName。而userEmail为null

(2)service实现类

1  @Override
2     public List<SysUser> selectByUser(SysUser sysUser) {
3         return userMapper.selectByUser(sysUser);
4     }
View Code

(3)mapper接口

List<SysUser> selectByUser(SysUser sysUser);

(4)mapper.xm<select id="selectByUser" resultType="com.example.demo.dao.SysUser">        select id,        user_name userName,

        user_password userPassword,
        user_email userEmail,
        user_info userInfo,
        head_img headImg,
        created_time createTime
        from sys_user
        where 1=1
        <if test="userName!=null and userName!=''">
            and user_name like concat('%',#{userName},'%')
        </if>
        <if test="userEmail!=null and userEmail!=''">
            and user_email=#{userEmail}
        </if>
    </select>

说明:1.if标签内有一个必填的属性test,test的值是一个符合OGNL要求的判断表达式,表达式的结果可以认为是ture或者false.
2.当有多个判断条件时,可以使用and或者or进行搭配。
3.上面两个if,它们是平级的关系,只要有满足if条件的,if标签内的 and user_x=... 这一句就会接在where语句后面。如果不满足,就不会有。
4.这里写了一个where 1=1 是为了保证当2个if语句都没有的时候,不会直接以where结束,这样sql语句就会报错。
这种写法where1=1不美观,后面可以采用where标签来拯救它。

(5)实体类

 1 package com.example.demo.dao;
 2 
 3 
 4 import java.sql.Date;
 5 
 6 public class SysUser {
 7     /**
 8      * 用户ID
 9      */
10     private Long id;
11     /**
12      * 用户名
13      */
14     private String userName;
15     /**
16      * 密码
17      */
18     private String userPassword;
19     /**
20      * 邮箱
21      */
22     private String userEmail;
23     /**
24      * 简介
25      */
26     private String userInfo;
27     /**
28      * 头像
29      */
30     private byte[] headImg;
31     /**
32      * 创建时间
33      */
34     private Date createTime;
35 
36     public Long getId() {
37         return id;
38     }
39 
40     public void setId(Long id) {
41         this.id = id;
42     }
43 
44     public String getUserName() {
45         return userName;
46     }
47 
48     public void setUserName(String userName) {
49         this.userName = userName;
50     }
51 
52     public String getUserPassword() {
53         return userPassword;
54     }
55 
56     public void setUserPassword(String userPassword) {
57         this.userPassword = userPassword;
58     }
59 
60     public String getUserEmail() {
61         return userEmail;
62     }
63 
64     public void setUserEmail(String userEmail) {
65         this.userEmail = userEmail;
66     }
67 
68     public String getUserInfo() {
69         return userInfo;
70     }
71 
72     public void setUserInfo(String userInfo) {
73         this.userInfo = userInfo;
74     }
75 
76     public byte[] getHeadImg() {
77         return headImg;
78     }
79 
80     public void setHeadImg(byte[] headImg) {
81         this.headImg = headImg;
82     }
83 
84     public Date getCreateTime() {
85         return createTime;
86     }
87 
88     public void setCreateTime(Date createTime) {
89         this.createTime = createTime;
90     }
91 }
View Code

采用postman模拟请求,会得到三条和名字模糊匹配的记录:

 1 [
 2     {
 3         "id": 3,
 4         "userName": "test1",
 5         "userPassword": "123456",
 6         "userEmail": "test1@mybatis.tk",
 7         "userInfo": "test1",
 8         "headImg": null,
 9         "createTime": "2020-03-04"
10     },
11     {
12         "id": 1001,
13         "userName": "test",
14         "userPassword": "123456",
15         "userEmail": "test@mybatis.tk",
16         "userInfo": "管理员",
17         "headImg": null,
18         "createTime": "2020-03-19"
19     },
20     {
21         "id": 1002,
22         "userName": "test1",
23         "userPassword": "123456",
24         "userEmail": "test1@mybatis.tk",
25         "userInfo": "test1",
26         "headImg": null,
27         "createTime": "2020-03-25"
28     },
29     {
30         "id": 1003,
31         "userName": "test1",
32         "userPassword": "123456",
33         "userEmail": "test1@mybatis.tk",
34         "userInfo": "test1",
35         "headImg": null,
36         "createTime": "2020-03-29"
37     },
38     {
39         "id": 1004,
40         "userName": "test1",
41         "userPassword": "123456",
42         "userEmail": "test1@mybatis.tk",
43         "userInfo": "test1",
44         "headImg": null,
45         "createTime": "2020-03-29"
46     }
47 ]
View Code

1.2 在UPDATE更新列中使用if标签

需求:只更新发生变化的字段。

(1)controller

1  @PostMapping("/updateBySelective")
2     int updateBySelective(SysUser sysUser){
3         sysUser.setUserName("hello");
4         sysUser.setId(1L);
5         return userService.updateBySelective(sysUser);
6     }
View Code

(2)service实现类

1 @Override
2     public int updateBySelective(SysUser sysUser) {
3         return userMapper.updateBySelective(sysUser);
4     }
View Code

(3)mapper接口

1  int updateBySelective(SysUser sysUser);
View Code

(4)mapper.xml

<update id="updateBySelective">
        update sys_user
        set
        <if test="userName!=null and userName!=''">
            user_name=#{userName},
        </if>
        <if test="userPassword!=null and userPassword!=''">
            user_password=#{userPassword},
        </if>
        <if test="userEmail!=null and userEmail!=''">
            user_email=#{userEmail},
        </if>
        <if test="userInfo!=null and userInfo!=''">
            user_info=#{userInfo},
        </if>
        <if test="headImg!=null">
            head_img=#{headImg,jdbcType=BLOB},
        </if>
        <if test="createTime!=null">
            created_time=#{createTime,jdbcType=TIMESTAMP},
        </if>
        id=#{id}
        where id=#{id}
    </update>

说明:1.这里 id=#{id}是为了防止所有if都不满足的时候语法错误。即使if中有个别满足的,也不能省去,否则sql语法错误。
这种写法不美观,仍然然可以通过where标签和set标签来解决。

 

 

 1.3 在INSERT动态插入列中使用if标签

需求:如果某一列的参数值不为空,就使用传入的值;如果传入参数为空,就使用数据库中默认的值(通常为空),而不使用传入的空值。

(1)controller

1 @PostMapping("/insertUser")
2     public int insertUser(){
3 
4        SysUser sysUser=new SysUser();
5        sysUser.setUserName("Tom");
6        sysUser.setUserEmail("aa.@qq.com");
7        sysUser.setUserInfo("作家");
8        return userService.insertUser(sysUser);
9     }
View Code

(2)service实现类

1 @Override
2     public int insertUser(SysUser sysUser) {
3         return userMapper.insertUser(sysUser);
4     }
View Code

(3)mapper接口

int insertUser(SysUser sysUser);

(4)mapper.xml

<insert id="insertUser">
    insert into sys_user(
    user_name,user_password,user_email,
    <if test="userInfo!=null and userInfo!=''">
        user_info,
    </if>
    head_img,created_time)
    values(
    #{userName},#{userPassword},#{userEmail},
    <if test="userInfo!=null and userInfo!=''">
        #{userInfo},
    </if>
    #{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})
</insert>

 

 

 二. choose(when、otherwise)

if标签只能实现if功能,没有else功能。于是可以通过本节的组合来实现if..else的功能。choose中农包含when和otherwise两个标签,一个choose中至少有一个when,有0个或1个otherwise.  

我的理解:when就相当于java中的else if,而otherwise就相当于java中的else。

需求:准备如下表。当ID有值的时候就优先采用ID进行查询匹配用户;如果ID没有值,那就采用用户名进行查询匹配的用户。

 

 (1)controller

1 @PostMapping("/selectByIdOrName")
2     SysUser selectByIdOrName(){
3         SysUser sysUser=new SysUser();
4         sysUser.setId(1L);
5         sysUser.setUserName("test3");
6         return userService.selectByIdOrName(sysUser);
7     }
View Code

(2)service实现类

1 @Override
2     public SysUser selectByIdOrName(SysUser sysUser) {
3         return userMapper.selectByIdOrName(sysUser);
4     }
View Code

(3)mapper接口

SysUser selectByIdOrName(SysUser sysUser);

(4)mapper.xml

<select id="selectByIdOrName" resultType="com.example.demo.dao.SysUser">
    select id,
    user_name userName,
    user_password userPassword,
    user_email userEmail,
    user_info userInfo,
    head_img headImg,
    created_time createTime
    from sys_user
    where 1=1
    <choose>
        <when test="id!=null">
            and id=#{id}
        </when>
        <when test="userName!=null and userName!=''">
            and user_name=#{userName}
        </when>
        <otherwise>
            and 1=2
        </otherwise>
    </choose>
</select>
{
    "id": 1,
    "userName": "test1",
    "userPassword": "123456",
    "userEmail": "admin@mybatis.tk",
    "userInfo": "管理员",
    "headImg": null,
    "createTime": "2020-03-01"
}

三. where、set、trim

 3.1 where标签

修改之前的where 1=1例子,姓名模糊匹配,邮箱完全匹配查询。

修改之前:

<select id="selectByUser" resultType="com.example.demo.dao.SysUser">
        select id,
        user_name userName,
        user_password userPassword,
        user_email userEmail,
        user_info userInfo,
        head_img headImg,
        created_time createTime
        from sys_user
        where 1=1
        <if test="userName!=null and userName!=''">
            and user_name like concat('%',#{userName},'%')
        </if>
        <if test="userEmail!=null and userEmail!=''">
            and user_email=#{userEmail}
        </if>
    </select>

直接将xml文件改为如下:

<select id="selectByUser" resultType="com.example.demo.dao.SysUser">
        select id,
        user_name userName,
        user_password userPassword,
        user_email userEmail,
        user_info userInfo,
        head_img headImg,
        created_time createTime
        from sys_user
        <where>
            <if test="userName!=null and userName!=''">
                and user_name like concat('%',#{userName},'%')
            </if>
            <if test="userEmail!=null and userEmail!=''">
                and user_email=#{userEmail}
            </if>
        </where>

    </select>
说明:当if都不满足的时候,where中就没有元素,就不会存在之前缺少where 1=1造成sql错误的问题。

3.2 set用法

还是之前的例子:

修改之前:

<update id="updateBySelective">
        update sys_user
        set
        <if test="userName!=null and userName!=''">
            user_name=#{userName},
        </if>
        <if test="userPassword!=null and userPassword!=''">
            user_password=#{userPassword},
        </if>
        <if test="userEmail!=null and userEmail!=''">
            user_email=#{userEmail},
        </if>
        <if test="userInfo!=null and userInfo!=''">
            user_info=#{userInfo},
        </if>
        <if test="headImg!=null">
            head_img=#{headImg,jdbcType=BLOB},
        </if>
        <if test="createTime!=null">
            created_time=#{createTime,jdbcType=TIMESTAMP},
        </if>
        id=#{id}
        where id=#{id}
    </update>

修改之后:

 1 <update id="updateUser">
 2         update sys_user
 3         set
 4         <foreach collection="_parameter" item="val" index="key" separator=",">
 5             ${key}=#{val}
 6         </foreach>
 7         where id=#{id}
 8     </update>
 9 
10     <update id="updateBySelective">
11         update sys_user
12         <set>
13             <if test="userName!=null and userName!=''">
14                 user_name=#{userName},
15             </if>
16             <if test="userPassword!=null and userPassword!=''">
17                 user_password=#{userPassword},
18             </if>
19             <if test="userEmail!=null and userEmail!=''">
20                 user_email=#{userEmail},
21             </if>
22             <if test="userInfo!=null and userInfo!=''">
23                 user_info=#{userInfo},
24             </if>
25             <if test="headImg!=null">
26                 head_img=#{headImg,jdbcType=BLOB},
27             </if>
28             <if test="createTime!=null">
29                 created_time=#{createTime,jdbcType=TIMESTAMP},
30             </if>
31             id=#{id}
32         </set>
33         where id=#{id}
34     </update>
View Code

这种只解决了逗号问题,不是很全面的解决问题,仍然需要

id=#{id}

 

3.3 trim标签

where和set标签的功能都能通过trim标签实现。

 

 举例:

(1)还是之前的用户名模糊匹配,邮箱完全匹配的例子:(使用trim标签去除多余的and关键字)

修改mapper.xml文件:

<select id="selectByUser" resultType="com.example.demo.dao.SysUser">
        select id,
        user_name userName,
        user_password userPassword,
        user_email userEmail,
        user_info userInfo,
        head_img headImg,
        created_time createTime
        from sys_user
        <trim prefix="where" prefixOverrides="and">
            <if test="userName!=null and userName!=''">
                and user_name like concat('%',#{userName},'%')
            </if>
            <if test="userEmail!=null and userEmail!=''">
                and user_email=#{userEmail}
            </if>
        </trim>

    </select>

效果一样的。但是就不会多写where1=1,并且指定了prefix为where。

 

posted @ 2020-11-25 14:53  Hermioner  阅读(1157)  评论(0编辑  收藏  举报