MyBatis动态Sql之if标签的用法详解

 更新时间:2019年07月08日 14:24:25   作者:申城异乡人   我要评论
这篇文章主要介绍了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("test@mybatis.tk");
    sysUserList = sysUserMapper.selectByUser(query);
    Assert.assertTrue(sysUserList.size() > 0);
    // 同时按用户民和邮箱查询
    query = new SysUser();
    query.setUserName("ad");
    query.setUserEmail("test@mybatis.tk");
    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, admin@mybatis.tk, 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: test@mybatis.tk(String)
TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time
TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 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), test@mybatis.tk(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("test@mybatis.tk");
    int result = sysUserMapper.updateByIdSelective(sysUser);
    Assert.assertEquals(1, result);
    // 查询id=1的用户
    sysUser = sysUserMapper.selectById(1L);
    // 修改后的名字保持不变,但是邮箱变成了新的
    Assert.assertEquals("admin", sysUser.getUserName());
    Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail());
  } finally {
    sqlSession.close();
  }
}

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

DEBUG [main] - ==> Preparing: UPDATE sys_user SET user_email = ?, id = ? WHERE id = ?
DEBUG [main] - ==> Parameters: test@mybatis.tk(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, test@mybatis.tk, 2019-06-27 18:21:07.0
DEBUG [main] - <== Total: 1

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

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

为了更好的理解该示例,我们先给sys_user表的user_email字段设置默认值:test@mybatis.tk,Sql语句如下:

ALTER TABLE sys_user
MODIFY COLUMN user_email VARCHAR(50) NULL DEFAULT 'test@mybatis.tk'
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("test@mybatis.tk", 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, test@mybatis.tk, 2019-07-08 11:40:37.0
DEBUG [main] - <== Total: 1

4. 源码

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

总结

以上所述是小编给大家介绍的MyBatis动态Sql之if标签的用法详解 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对澳门金沙网上娱乐网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

  • java实现gif动画效果(java显示动态图片)

    java实现gif动画效果(java显示动态图片)

    这篇文章主要介绍了java实现gif动画效果示例(java显示动态图片),需要的朋友可以参考下
    2014-04-04
  • JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    这篇文章主要介绍了JAVA多线程之中断机制stop()、interrupted()、isInterrupted()的相关资料,需要的朋友可以参考下
    2016-05-05
  • Git和Maven的子模块简单实践

    Git和Maven的子模块简单实践

    今天小编就为大家分享一篇关于Git和Maven的子模块简单实践,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java代码注释规范详解

    Java代码注释规范详解

    代码附有注释对程序开发者来说非常重要,随着技术的发展,在项目开发过程中,必须要求程序员写好代码注释,这样有利于代码后续的编写和使用。下面给大家分享java代码注释的规范,需要的朋友参考下
    2016-02-02
  • Java中如何动态创建接口的实现方法

    Java中如何动态创建接口的实现方法

    这篇文章主要介绍了Java中如何动态创建接口的实现方法的相关资料,需要的朋友可以参考下
    2017-09-09
  • Spring Cloud Eureka 服务上下线监控的实现

    Spring Cloud Eureka 服务上下线监控的实现

    这篇文章主要介绍了Spring Cloud Eureka 服务上下线监控的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • windows下zookeeper配置java环境变量的方法

    windows下zookeeper配置java环境变量的方法

    今天小编就为大家分享一篇关于windows下zookeeper配置java环境变量的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Java数据导入功能之读取Excel文件实例

    Java数据导入功能之读取Excel文件实例

    这篇文章主要介绍了Java数据导入功能之读取Excel文件实例,本文给出了jar包的下载地址以及读取Excel文件的代码实例,需要的朋友可以参考下
    2015-06-06
  • 探究Java常量本质及三种常量池(小结)

    探究Java常量本质及三种常量池(小结)

    这篇文章主要介绍了探究Java常量本质及三种常量池(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Java调用Windows的DOS命令的方法

    Java调用Windows的DOS命令的方法

    这篇文章主要介绍了Java调用Windows的DOS命令的方法,其主要内容思路是实现调用Windows的ipconfig命令,然后将输出的信息通过IO流输出到控制台。有需要的小伙伴参考下
    2015-02-02

最新评论