MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
本篇博客主要讲解如何使用choose,where,set标签生成动态的Sql。
1. choose 用法
假设有这样1个需求:当参数id有值时优先使用id查询,当id没有值时就去判断用户名是否有值,如果有值就用用户名查询,如果没值,就使查询无结果。
首先,我们在接口SysUserMapper中添加如下方法:
/**
* 根据用户id或用户名查询
*
* @param sysUser
* @return
*/
SysUser selectByIdOrUserName(SysUser sysUser);
然后在对应的SysUserMapper.xml中添加如下代码:
<select id="selectByIdOrUserName" resultType="com.zwwhnly.mybatisaction.model.SysUser">
SELECT id,
user_name,
user_password,
user_email,
create_time
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>
注意事项:
在以上的代码中,如果没有otherwise这个限制条件,当id和userName都为null时,所有的用户都会被查询出来,但我们接口的返回值是SysUser,当查询结果是多个时就会报错。添加otherwise条件后,由于where条件不满足,因此在这种情况下就查询不到结果。
最后,在SysUserMapperTest测试类中添加如下测试方法:
@Test
public void testSelectByIdOrUserName() {
SqlSession sqlSession = getSqlSession();
try {
SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
// 按id查询
SysUser query = new SysUser();
query.setId(1L);
query.setUserName("admin");
SysUser sysUser = sysUserMapper.selectByIdOrUserName(query);
Assert.assertNotNull(sysUser);
// 只按userName查询
query.setId(null);
sysUser = sysUserMapper.selectByIdOrUserName(query);
Assert.assertNotNull(sysUser);
// id 和 userName 都为空
query.setUserName(null);
sysUser = sysUserMapper.selectByIdOrUserName(query);
Assert.assertNull(sysUser);
} finally {
sqlSession.close();
}
}
运行测试代码,测试通过,输出日志如下:
DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND id = ?
DEBUG [main] - ==> Parameters: 1(Long)
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_name = ?
DEBUG [main] - ==> Parameters: admin(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 1 = 2
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 0
2. where 用法
where标签的作用:如果该标签包含的元素中有返回值,就插入一个where,如果where后面的字符串是以AND或者OR开头的,就将它们剔除。
假设有这样1个需求:根据用户的输入条件来查询用户列表,如果输入了用户名,就根据用户名模糊查询,如果输入了邮箱,就根据邮箱精确查询,如果同时输入了用户名和邮箱,就用这两个条件去匹配用户。
首先,我们在接口SysUserMapper中添加如下方法:
/**
* 根据动态条件查询用户信息(使用Where标签)
*
* @param sysUser
* @return
*/
List<SysUser> selectByUserWhere(SysUser sysUser);
然后在对应的SysUserMapper.xml中添加如下代码:
<select id="selectByUserWhere" resultType="com.zwwhnly.mybatisaction.model.SysUser">
SELECT id,
user_name,
user_password,
user_email,
create_time
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元素中没有内容,此时的Sql语句不会有where,语法正确。
如果if条件满足,where元素的内容就是以AND开头的条件,where会自动去掉开头的and,保证Sql语句的正确。
最后,在SysUserMapperTest测试类中添加如下测试方法:
@Test
public void testSelectByUserWhere() {
SqlSession sqlSession = getSqlSession();
try {
SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
// 只按用户名查询
SysUser query = new SysUser();
query.setUserName("ad");
List<SysUser> sysUserList = sysUserMapper.selectByUserWhere(query);
Assert.assertTrue(sysUserList.size() > 0);
// 只按邮箱查询
query = new SysUser();
query.setUserEmail("test@mybatis.tk");
sysUserList = sysUserMapper.selectByUserWhere(query);
Assert.assertTrue(sysUserList.size() > 0);
// 同时按用户民和邮箱查询
query = new SysUser();
query.setUserName("ad");
query.setUserEmail("test@mybatis.tk");
sysUserList = sysUserMapper.selectByUserWhere(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 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 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 user_name LIKE CONCAT('%',?,'%') AND user_email = ?
DEBUG [main] - ==> Parameters: ad(String), test@mybatis.tk(String)
DEBUG [main] - <== Total: 0
3. set 用法
set标签的作用:如果该标签包含的元素中有返回值,就插入一个set,如果set后面的字符串是以,结尾的,就将这个逗号剔除。
假设有这样1个需求:更新用户信息的时候不能将原来有值但没有发生变化的字段更新为空或null,即只更新有值的字段。
首先,我们在接口SysUserMapper中添加如下方法:
/**
* 根据主键选择性更新用户信息(使用Set标签)
*
* @param sysUser
* @return
*/
int updateByIdSelectiveSet(SysUser sysUser);
然后在对应的SysUserMapper.xml中添加如下代码:
<update id="updateByIdSelectiveSet">
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},
</set>
WHERE id = #{id}
</update>
注意事项:为了避免所有的条件都不满足,生成的Sql语句没有set标签,因此在最后加上了id = #{id},这样必然存在的赋值。
最后,在SysUserMapperTest测试类中添加如下测试方法:
@Test
public void testUpdateByIdSelectiveSet() {
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.updateByIdSelectiveSet(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
4. 源码及参考
源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。
刘增辉《MyBatis从入门到精通》
原创不易,如果觉得文章能学到东西的话,欢迎点个赞、评个论、关个注,这是我坚持写作的最大动力。
如果有兴趣,欢迎添加我的微信:zwwhnly,等你来聊技术、职场、工作等话题(PS:我是一名奋斗在上海的程序员)。
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法的更多相关文章
- MyBatis基础入门《二十》动态SQL(foreach)
MyBatis基础入门<二十>动态SQL(foreach) 1. 迭代一个集合,通常用于in条件 2. 属性 > item > index > collection : ...
- MyBatis基础入门《十九》动态SQL(set,trim)
MyBatis基础入门<十九>动态SQL(set,trim) 描述: 1. 问题 : 更新用户表数据时,若某个参数为null时,会导致更新错误 2. 分析: 正确结果: 若某个参数为nul ...
- MyBatis基础入门《十八》动态SQL(if-where)
MyBatis基础入门<十八>动态SQL(if-where) 描述: 代码是在<MyBatis基础入门<十七>动态SQL>基础上进行改造的,不再贴所有代码,仅贴改动 ...
- Mybatis学习笔记12 - 动态sql之choose(when otherwise)标签
choose (when, otherwise):分支选择:带了break的swtich-case 示例代码: 接口定义: package com.mybatis.dao; import com.my ...
- MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用if标签生成动 ...
- MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用foreach ...
- MyBatis从入门到精通(第4章):MyBatis动态SQL【foreach、bind、OGNL用法】
(第4章):MyBatis动态SQL[foreach.bind.OGNL用法] 4.4 foreach 用法 SQL 语句中有时会使用 IN 关键字,例如 id in (1,2,3).可以使用 ${i ...
- MyBatis从入门到精通(第9章):Spring集成MyBatis(下)
MyBatis从入门到精通(第9章):Spring集成MyBatis(下) springmvc执行流程原理 mybatis-spring 可以帮助我们将MyBatis代码无缝整合到Spring中.使 ...
- MyBatis从入门到精通(第9章):Spring集成MyBatis(上)
MyBatis从入门到精通(第9章):Spring集成MyBatis(上) Spring是一个为了解决企业级Web应用开发过程中面临的复杂性,而被创建的一个非常流行的轻量级框架. mybatis-sp ...
随机推荐
- 卷积(convolution)与相关(correlation)(matlab 实现)
1. 卷积(convolution) 输出 y(n) 是作为在 x(k) 和 h(n−k)(反转和移位)重叠之下的样本和求出的. 考虑下面两个序列: x(n)=[3,11,7,0,−1,4,2],−3 ...
- 【winows7+android-ndk-r9+Cygwin 】cocos2dx 2.*游戏移植Android平台完全手册
为了有不少走的弯路.这里简要记录cocos2d开发环境的搭建.android开发环境搭建.android NDK环境搭建.终于实现cocos2dx 2.* 游戏Android平台移植. 转载请注明出处 ...
- 大数据_zookeeper环境搭建中的几个坑
文章目录 [] Zookeeper简介 关于zk的介绍, zk的paxos算法, 网上已经有各位大神在写了, 本文主要写我在搭建过程中的几个极有可能遇到的坑. Zookeeper部署中的坑 坑之一 E ...
- 潜移默化学会WPF--值转换器
原文:潜移默化学会WPF--值转换器 1. binding 后面的stringFormat的写法----连接字符串 <TextBlock Text="{Binding Path=Qty ...
- CentOS 6安装桌面
安装图形界面 yum -y groupinstall "X Window System" "Chinese Support" "Desktop&quo ...
- ASP .NET DropDownList多级联动事件
思路 假如有三级省.市.区,先加载出所有省选择省之后,加载出该省所有市选择市之后,加载出该市所有区重新选择省,则清空市和区重新选择市,则清空区想好数据结构,不同的数据结构做法不同 例子 数据结构 pu ...
- 安装CUDA和cuDNN
GPU和CPU区别 1,CPU主要用于处理通用逻辑,以及各种中断事物 2,GPU主要用于计算密集型程序,可并行运作: NVIDIA 的 GeForce 显示卡系列采用 GPU 特性进行快速计算,渲染电 ...
- PHP XDebug Sublime Text 单步调试
前置环境:已经安装好LNMP 1. 安装xdebug 可以通过pear包管理来安装 sudo apt-get install php-pear sudo pecl install xdebug 这里我 ...
- 用VS2010构建MASM的编程环境,开始使用MASM(翻译自《Inetl汇编语言程序设计》一书的作者Kip R. Irvine的文章Getting Started with MASM),两种方法搭建IA-32汇编设计环境
http://blog.csdn.net/jinsonghu/article/details/5688020 http://blog.csdn.net/jinsonghu/article/detail ...
- 使用Newtonsoft.Json输出JSON
安装: Install-Package Newtonsoft.Json 代码: //序列化DataTable DataTable dt = new DataTable(); dt.Columns.Ad ...