MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法
本篇博客主要讲解如何使用if标签生成动态的Sql,主要包含以下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从入门到精通》
MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法的更多相关文章
- 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从入门到精通(八):MyBatis动态Sql之foreach标签的用法
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用foreach ...
- MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用choose, ...
- 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 ...
- MyBatis基础入门《十六》缓存
MyBatis基础入门<十六>缓存 >> 一级缓存 >> 二级缓存 >> MyBatis的全局cache配置 >> 在Mapper XML文 ...
- MyBatis从入门到精通(一):MyBatis入门
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. MyBatis简介 2001 ...
随机推荐
- sql server中使用链接服务器访问oracle数据库
一. 安装配置oracle客户端 要访问orcale数据,必须在访问的客户端机器上安装oracle客户端. Orcale有两种形式的客户端: l 完整的客户端 包括访问服务器端数据库 ...
- matlab figure 调整大小、字体、线宽
用 matlab 画了一张图,投稿时要缩小,缩小后字体就会过小或者发虚. 解决办法: % figure resize set(gcf,'Position',[100 100 260 220]); se ...
- 你所不知道的 Kindle - 阅读微信公众号文章
Kindle 是一款非常优秀的阅读设备,它为我们提供了非常舒服的阅读体验,并且配合强大的亚马逊图书资源,应该是目前最好的阅读设备之一.Kindle 在已有的成就下还一直在努力提升用户体验.为中国用户开 ...
- glibc头文件和宏定义
头文件没啥好说的,无非就是" "和< >的区别,这估计只要是学过C/C++的人都明白.现在的编译器对头文件的包含顺序没有要求,但老的C实现则不一样.当然,我们现在无需关 ...
- 【转载】centos7+tomcat部署JavaWeb项目超详细步骤
我们平时访问的网站大多都是发布在云服务器上的,比如阿里云.腾讯云等.对于新手,尤其是没有接触过linux系统的人而言是比较有困难的,而且至今使用云服务器也是有成本的,很多时候我们可以通过虚拟机自己搭建 ...
- WPF 数据模板的使用
<Window x:Class="CollectionBinding.MainWindow" xmlns="http://schemas.micros ...
- ASP POST请求
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- 数据绑定(七)使用ObjectDataProvider对象作为Binding的Source
原文:数据绑定(七)使用ObjectDataProvider对象作为Binding的Source ObjectDataProvider就是把对象作为数据源提供给Binding,类似的还有XmlData ...
- Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化
原文:Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化 [函数名称] 双峰法图像二值化 WriteableBitmap PeakshistogramThSegment( ...
- MS SQL SERVER搜索某个表的主键所在的列名
原文:MS SQL SERVER搜索某个表的主键所在的列名 SELECT SYSCOLUMNS.name FROM SYSCOLUMNS,SYSOBJECTS,SYSINDEXES,SYSINDEX ...