MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法

最近在读刘增辉老师所著的《MyBatis从入门到精通》一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸!

本篇博客主要讲解如何使用if标签生成动态的Sql,主要包含以下3个场景:

  1. 根据查询条件实现动态查询
  2. 根据参数值实现动态更新某些列
  3. 根据参数值实现动态插入某些列

1. 使用if标签实现动态查询

假设有这样1个需求:根据用户的输入条件来查询用户列表,如果输入了用户名,就根据用户名模糊查询,如果输入了邮箱,就根据邮箱精确查询,如果同时输入了用户名和邮箱,就用这两个条件去匹配用户。

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据动态条件查询用户信息
 *
 * @param sysUser
 * @return
 */
List<SysUser> selectByUser(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<select id="selectByUser" resultType="com.zwwhnly.mybatisaction.model.SysUser">
    SELECT  id,
            user_name,
            user_password,
            user_email,
            create_time
    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属性必填,该属性值是一个符合OGNL要求的判断表达式,一般只用true或false作为结果。

2)判断条件property != null 或 property == null,适用于任何类型的字段,用于判断属性值是否为空。

3)判断条件property != ‘‘ 或 property == ‘‘,仅适用于String类型的字段,用于判断是否为空字符串。

4)当有多个判断条件时,使用and或or进行连接,嵌套的判断可以使用小括号分组,and相当于Java中的与(&&),or相关于Java中的或(||)。

所以上面代码的意思就是先判断字段是否为null,然后再判断字段是否为空字符串。

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testSelectByUser() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        // 只按用户名查询
        SysUser query = new SysUser();
        query.setUserName("ad");
        List<SysUser> sysUserList = sysUserMapper.selectByUser(query);
        Assert.assertTrue(sysUserList.size() > 0);

        // 只按邮箱查询
        query = new SysUser();
        query.setUserEmail("[email protected]");
        sysUserList = sysUserMapper.selectByUser(query);
        Assert.assertTrue(sysUserList.size() > 0);

        // 同时按用户民和邮箱查询
        query = new SysUser();
        query.setUserName("ad");
        query.setUserEmail("[email protected]");
        sysUserList = sysUserMapper.selectByUser(query);
        // 由于没有同时符合这两个条件的用户,因此查询结果数为0
        Assert.assertTrue(sysUserList.size() == 0);
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT(‘%‘,?,‘%‘)

DEBUG [main] - ==> Parameters: ad(String)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1, admin, 123456, [email protected], 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_email = ?

DEBUG [main] - ==> Parameters: [email protected](String)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1001, test, 123456, [email protected], 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT(‘%‘,?,‘%‘) AND user_email = ?

DEBUG [main] - ==> Parameters: ad(String), [email protected](String)

DEBUG [main] - <== Total: 0

2. 使用if标签实现动态更新

假设有这样1个需求:更新用户信息的时候不能将原来有值但没有发生变化的字段更新为空或null,即只更新有值的字段。

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据主键选择性更新用户信息
 *
 * @param sysUser
 * @return
 */
int updateByIdSelective(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<update id="updateByIdSelective">
    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">
        create_time = #{createTime,jdbcType=TIMESTAMP},
    </if>
    id = #{id}
    WHERE id = #{id}
</update>

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testUpdateByIdSelective() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        SysUser sysUser = new SysUser();
        // 更新id=1的用户
        sysUser.setId(1L);
        // 修改邮箱
        sysUser.setUserEmail("[email protected]");

        int result = sysUserMapper.updateByIdSelective(sysUser);
        Assert.assertEquals(1, result);

        // 查询id=1的用户
        sysUser = sysUserMapper.selectById(1L);
        // 修改后的名字保持不变,但是邮箱变成了新的
        Assert.assertEquals("admin", sysUser.getUserName());
        Assert.assertEquals("[email protected]", sysUser.getUserEmail());
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: UPDATE sys_user SET user_email = ?, id = ? WHERE id = ?

DEBUG [main] - ==> Parameters: [email protected](String), 1(Long), 1(Long)

DEBUG [main] - <== Updates: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1, admin, 123456, [email protected], 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

3. 使用if标签实现动态插入

假设有这样1个需求:往数据库表中插入数据的时候,如果某一列的参数值不为空,就使用传入的值,如果传入的参数值为空,就使用数据库中的默认值(通常是空),而不使用传入的空值。

为了更好的理解该示例,我们先给sys_user表的user_email字段设置默认值:[email protected],Sql语句如下:

ALTER TABLE sys_user
MODIFY COLUMN user_email VARCHAR(50) NULL DEFAULT  '[email protected]'
COMMENT '邮箱'
AFTER user_password;

首先,我们在接口SysUserMapper中添加如下方法:

/**
 * 根据传入的参数值动态插入列
 *
 * @param sysUser
 * @return
 */
int insertSelective(SysUser sysUser);

然后在对应的SysUserMapper.xml中添加如下代码:

<insert id="insertSelective" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO sys_user(user_name, user_password,
    <if test="userEmail != null and userEmail != ''">
        user_email,
    </if>
    user_info, head_img, create_time)
    VALUES (#{userName},#{userPassword},
    <if test="userEmail != null and userEmail != ''">
        #{userEmail},
    </if>
    #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})
</insert>

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Test
public void testInsertSelective() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        SysUser sysUser = new SysUser();
        sysUser.setUserName("test-selective");
        sysUser.setUserPassword("123456");
        sysUser.setUserInfo("test info");
        sysUser.setCreateTime(new Date());

        sysUserMapper.insertSelective(sysUser);

        // 获取刚刚插入的数据
        sysUser = sysUserMapper.selectById(sysUser.getId());
        // 因为没有指定userEmail,所以用的是数据库的默认值
        Assert.assertEquals("[email protected]", sysUser.getUserEmail());
    } finally {
        sqlSession.close();
    }
}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: INSERT INTO sys_user(user_name, user_password, user_info, head_img, create_time) VALUES (?,?, ?,?,?)

DEBUG [main] - ==> Parameters: test-selective(String), 123456(String), test info(String), null, 2019-07-08 11:40:36.927(Timestamp)

DEBUG [main] - <== Updates: 1

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ?

DEBUG [main] - ==> Parameters: 1021(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time

TRACE [main] - <== Row: 1021, test-selective, 123456, [email protected], 2019-07-08 11:40:37.0

DEBUG [main] - <== Total: 1

4. 源码

源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。

5. 参考

刘增辉《MyBatis从入门到精通》

原文地址:https://www.cnblogs.com/zwwhnly/p/11150265.html

时间: 2024-10-11 11:45:51

MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法的相关文章

mybatis从入门到精通(四) 动态SQL

mybatis从入门到精通(四) 动态SQL 一丶简介 Mybatis的强大特性之一是动态SQL, 它可以动态拼接sql语句, 减轻开发的工作量. Mybatis的动态sql标签如下4种类型 1. if 2. choose (when, otherwise) 3. trim (where, set) 4. foreach 二丶<if/> <if/>标签相当于java语言中的if语句, 通过判断是否符合预置条件来拼接sql语句.其中判断条件可以使用ongl表达式, 如e.method

MyBatis从入门到精通(第4章):MyBatis动态SQL

(第4章):MyBatis动态SQL:本章详细介绍了MyBatis最强大的动态SQL功能,通过丰富的示例讲解了各种动态SQL的用法,还提供了动态SQL中常用的OGNL用法. (第4章):MyBatis动态SQL MyBatis 3.5.2版本采用了功能强大的OGNL(Object-Graph Navigation Language)表达式语言,以下是MyBatis的动态SQL在XML中支持的几种标签. if choose(when.otherwise) trim(where.set) forea

mybatis从入门到精通(二) 增删查改

mybatis从入门到精通(二) 增删查改 一丶前言 "增删查改"是后台开发的常用操作, 因此, 学习mybatis或者其他orm框架有必要统一学习一下"增删查改". 二丶准备开发环境 使用"mybatis从入门到精通(一) 入门"准备的开发环境 三丶查 -- <select/> UserMapper.java User selectUser(@Param("userId") int userId); UserMa

mybatis从入门到精通(五) sqlSession API的使用

mybatis从入门到精通(五) sqlSession API的使用  一丶简介 SqlSession类似于mybatis对外的接口层, 它几乎囊括了所有对外的api, 因此, 学习SqlSession的使用方法对于了解mybatis还是有必要的. 对应官方文档 二丶配置SqlSession的环境<environment/> <environment/> 主要包括了两种配置, 事务管理和数据源. 这里的配置仅仅是用于学习, 实际应用一般是将事务交由Spring容器管理, 数据源一般

MyBatis从入门到精通(一):MyBatis入门

最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. MyBatis简介 ? 2001年,Clinton Begin发起了一个名为iBATIS的开源项目,最初侧重于密码软件的研发,后来发展成为一款基于Java的持久层框架. ? 2004年,Clinton将iBATIS的名字和源码捐赠给了Apache软件基金会. ? 2010年,核心开发团队决定离开Apache软件基金会,并且将iBATIS改名

mybatis从入门到精通(三) 结果映射

mybatis从入门到精通(三) 结果映射 一丶什么是结果映射 结果映射是用于将数据库表字段和实体类中的属性名映射起来, 即究竟是哪个字段名与属性名对应. 映射之后, 即可通过mybatis将从数据库查询的结果转换成对应的实体类对象类型, 除去了人工转换的麻烦. 二丶自动映射 所谓的自动映射, 即是默认java实体类的属性名是驼峰式, 而数据库表字段名是以下划线分隔, 如 属性名userName 与 表字段user_name相对应, 如果是这种简单通用的规则, 即可通过配置mybatis, 使得

MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射

最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解MyBatis中如何使用collection标签实现查询结果一对多映射. 1. 使用collection标签 需求:根据用户id查询用户信息的同时获取用户拥有的角色,一个用户可以拥有1个或多个角色. 一般情况下,不建议直接修改数据库表对应的实体类. 所以这里我们延用之前博客中新建的类SysUserExtend,并添加如下代码,如下

MyBatis从入门到精通(十二):使用collection标签实现嵌套查询

最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解使用collection标签实现嵌套查询的方法. 1. 需求升级 在上篇博客中,我们实现了需求:根据用户id查询用户信息的同时获取用户拥有的角色. 因为角色可以拥有多个权限,所以本篇博客我们升级需求为:根据用户id查询用户信息的同时获取用户拥有的角色以及角色包含的权限. 2. 实现方式 因为我们需要使用到权限表的映射,所以我们需要

深入浅出Mybatis系列(九)---强大的动态SQL(转载)

原文出处:http://www.cnblogs.com/dongying/p/4092662.html 上篇文章<深入浅出Mybatis系列(八)---mapper映射文件配置之select.resultMap>简单介绍了mybatis的查询,至此,CRUD都已讲完.本文将介绍mybatis强大的动态SQL. 那么,问题来了: 什么是动态SQL? 动态SQL有什么作用? 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Myba