9、MyBatis的动态SQL
文章目录
- 动态SQL
- sql标签
- if标签
- where标签
- set标签
- trim标签
- 查询
- 更新
- 插入
- foreach
- choose...when...otherwise
动态SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
数据库环境准备
-- 动态SQL
USE mybatis;CREATE TABLE IF NOT EXISTS `user` (uid INT NOT NULL AUTO_INCREMENT,uname VARCHAR(50) NOT NULL,upassword VARCHAR(50) NOT NULL,u_nickname VARCHAR(50) NOT NULL,PRIMARY KEY (uid)
);INSERT INTO `user` VALUES (NULL, '赵云', '123456', '常山赵子龙'), (NULL, '张飞', 'asdfff', '燕人张飞'), (NULL, '关羽', 'ghhjkl', '关云长');
sql标签
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {private static final long serialVersionUID = -5970028623059313270L;private Integer uid;private String uname;private String upassword;private String unickname;
}
public interface UserMapper {User selectByPrimaryKey(Integer uid);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.westos.mapper.UserMapper"><sql id="baseColumn">uid, uname, upassword, u_nickname</sql><select id="selectByPrimaryKey" resultType="User">select<include refid="baseColumn"/>fromuserwhereuid = #{uid}</select>
</mapper>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = mapper.selectByPrimaryKey(1);System.out.println(JSON.toJSONString(user, true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user where uid = ?
==> Parameters: 1(Integer)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 1, 赵云, 123456, 常山赵子龙
<== Total: 1
{"uid":1,"uname":"赵云","unickname":"常山赵子龙","upassword":"123456"
}
if标签
//根据条件查询
//使用if标签
List<User> selectAll(User user);
<select id="selectAll" resultType="User">select<include refid="baseColumn"/>fromuserwhere 1 = 1<if test="uid != null">and uid = #{uid}</if><if test="uname != null and uname != ''">and uname = #{uname}</if><if test="upassword != null and upassword != ''">and upassword = #{upassword}</if>
</select>
如果传递的User对象属性都为null,那么就是查询全部User。
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(2);user.setUname("张飞");List<User> users = mapper.selectAll(user);System.out.println(JSON.toJSONString(users, true));} catch (IOException e) {e.printStackTrace();}
}
User对象的uid和uname是有值的。
==> Preparing: select uid, uname, upassword, u_nickname from user where 1 = 1 and uid = ? and uname = ?
==> Parameters: 2(Integer), 张飞(String)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 2, 张飞, asdfff, 燕人张飞
<== Total: 1
[{"uid":2,"uname":"张飞","unickname":"燕人张飞","upassword":"asdfff"}
]
where标签
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
//根据条件查询
//使用where标签
List<User> selectAll2(User user);
<!--where标签 标签的特点是只有满足if判断条件,才输出where,而且可以去除 第一个 and / or-->
<select id="selectAll2" resultType="User">select<include refid="baseColumn"/>fromuser<where><if test="uid != null">and uid = #{uid}</if><if test="uname != null and uname != ''">and uname = #{uname}</if><if test="upassword != null and upassword != ''">and upassword = #{upassword}</if></where>
</select>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(2);user.setUname("张飞");List<User> users = mapper.selectAll2(user);System.out.println(JSON.toJSONString(users, true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user WHERE uid = ? and uname = ?
==> Parameters: 2(Integer), 张飞(String)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 2, 张飞, asdfff, 燕人张飞
<== Total: 1
[{"uid":2,"uname":"张飞","unickname":"燕人张飞","upassword":"asdfff"}
]
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUname("");List<User> users = mapper.selectAll2(user);System.out.println(JSON.toJSONString(users, true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user
==> Parameters:
<== Columns: uid, uname, upassword, u_nickname
<== Row: 1, 赵云, 123456, 常山赵子龙
<== Row: 2, 张飞, asdfff, 燕人张飞
<== Row: 3, 关羽, ghhjkl, 关云长
<== Total: 3
[{"uid":1,"uname":"赵云","unickname":"常山赵子龙","upassword":"123456"},{"uid":2,"uname":"张飞","unickname":"燕人张飞","upassword":"asdfff"},{"uid":3,"uname":"关羽","unickname":"关云长","upassword":"ghhjkl"}
]
set标签
void updateUser(User user);
<!--set标签-->
<update id="updateUser">updateuser<set><if test="uname != null and uname != ''">uname = #{uname},</if><if test="upassword != null and upassword != ''">upassword = #{upassword},</if><if test="unickname != null and unickname != ''">u_nickname = #{unickname},</if></set>where uid = #{uid}
</update>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(3);user.setUname("黄忠");user.setUpassword("huang");user.setUnickname("汉升");mapper.updateUser(user);sqlSession.commit();System.out.println(JSON.toJSONString(mapper.selectByPrimaryKey(3), true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: update user SET uname = ?, upassword = ?, u_nickname = ? where uid = ?
==> Parameters: 黄忠(String), huang(String), 汉升(String), 3(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@10a035a0]
==> Preparing: select uid, uname, upassword, u_nickname from user where uid = ?
==> Parameters: 3(Integer)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 3, 黄忠, huang, 汉升
<== Total: 1
{"uid":3,"uname":"黄忠","unickname":"汉升","upassword":"huang"
}
trim标签
<select id="findActiveBlogLike"resultType="Blog">SELECT * FROM BLOG<where><if test="state != null">state = #{state}</if><if test="title != null">AND title like #{title}</if><if test="author != null and author.name != null">AND author_name like #{author.name}</if></where>
</select>
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">...
</trim>
查询
//使用trim标签
List<User> selectAll3(User user);
<!--trim标签的属性,prefix增加一个前缀,prefixOverrides去除一个前缀-->
<!--suffix增加一个后缀,suffixOverrides去除一个后缀-->
<!--主要是在插入、更新时使用-->
<select id="selectAll3" resultType="User">select<include refid="baseColumn"/>fromuser<trim prefix="where" prefixOverrides="and |or "><if test="uid != null">and uid = #{uid}</if><if test="uname != null and uname.trim != ''">and uname = #{uname}</if></trim>
</select>
prefix:增加一个前缀
prefixOverrides:去除一个前缀。
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(3);user.setUname("黄忠");System.out.println(JSON.toJSONString(mapper.selectAll3(user), true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user where uid = ? and uname = ?
==> Parameters: 3(Integer), 黄忠(String)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 3, 黄忠, huang, 汉升
<== Total: 1
[{"uid":3,"uname":"黄忠","unickname":"汉升","upassword":"huang"}
]
更新
//使用trim标签
void updateUser2(User user);
<!--prefix增加一个前缀,suffixOverrides去除一个后缀-->
<update id="updateUser2">updateuser<trim prefix="set" suffixOverrides=","><if test="uname != null and uname.trim != ''">uname = #{uname},</if><if test="upassword != null and upassword.trim != ''">upassword = #{upassword},</if><if test="unickname != null and unickname.trim != ''">u_nickname = #{unickname},</if></trim>where uid = #{uid}
</update>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(3);user.setUname("马超");user.setUpassword("ma");user.setUnickname("马儿");mapper.updateUser2(user);sqlSession.commit();System.out.println(JSON.toJSONString(mapper.selectAll3(user), true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: update user set uname = ?, upassword = ?, u_nickname = ? where uid = ?
==> Parameters: 马超(String), ma(String), 马儿(String), 3(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@481a15ff]
==> Preparing: select uid, uname, upassword, u_nickname from user where uid = ? and uname = ?
==> Parameters: 3(Integer), 马超(String)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 3, 马超, ma, 马儿
<== Total: 1
[{"uid":3,"uname":"马超","unickname":"马儿","upassword":"ma"}
]
插入
//使用trim标签
void insertUser(User user);
<insert id="insertUser">insert into user<trim prefix="(" suffix=")" suffixOverrides=","><if test="uname != null">uname,</if><if test="upassword != null">upassword,</if><if test="unickname != null">u_nickname,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="uname != null">#{uname},</if><if test="upassword != null">#{upassword},</if><if test="unickname != null">#{unickname},</if></trim>
</insert>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUname("黄忠");user.setUpassword("huang");user.setUnickname("汉升");mapper.insertUser(user);sqlSession.commit();System.out.println(JSON.toJSONString(mapper.selectAll(null), true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: insert into user ( uname, upassword, u_nickname ) values ( ?, ?, ? )
==> Parameters: 黄忠(String), huang(String), 汉升(String)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@706a04ae]
==> Preparing: select uid, uname, upassword, u_nickname from user where 1 = 1
==> Parameters:
<== Columns: uid, uname, upassword, u_nickname
<== Row: 1, 赵云, 123456, 常山赵子龙
<== Row: 2, 张飞, asdfff, 燕人张飞
<== Row: 3, 马超, ma, 马儿
<== Row: 4, 黄忠, huang, 汉升
<== Total: 4
[{"uid":1,"uname":"赵云","unickname":"常山赵子龙","upassword":"123456"},{"uid":2,"uname":"张飞","unickname":"燕人张飞","upassword":"asdfff"},{"uid":3,"uname":"马超","unickname":"马儿","upassword":"ma"},{"uid":4,"uname":"黄忠","unickname":"汉升","upassword":"huang"}
]
foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:
//使用foreach标签
List<User> select(List<Integer> list);
<select id="select" resultType="User">select<include refid="baseColumn"/>fromuser<trim prefix="where">uid in <foreach collection="list" open="(" close=")" separator="," index="index" item="item">#{item}</foreach></trim>
</select>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 2, 3, 4));List<User> users = mapper.select(arrayList);System.out.println(JSON.toJSONString(users, true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user where uid in ( ? , ? , ? , ? )
==> Parameters: 1(Integer), 2(Integer), 3(Integer), 4(Integer)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 1, 赵云, 123456, 常山赵子龙
<== Row: 2, 张飞, asdfff, 燕人张飞
<== Row: 3, 马超, ma, 马儿
<== Row: 4, 黄忠, huang, 汉升
<== Total: 4
[{"uid":1,"uname":"赵云","unickname":"常山赵子龙","upassword":"123456"},{"uid":2,"uname":"张飞","unickname":"燕人张飞","upassword":"asdfff"},{"uid":3,"uname":"马超","unickname":"马儿","upassword":"ma"},{"uid":4,"uname":"黄忠","unickname":"汉升","upassword":"huang"}
]
choose…when…otherwise
//使用choose...when...otherwise标签
User select2(User user);
<select id="select2" resultType="User">select<include refid="baseColumn"/>fromuserwhere<choose><when test="uid != null">uid = #{uid}</when><when test="uname != null">uname = #{uname}</when><otherwise>upassword = #{upassword}</otherwise></choose>
</select>
@Test
public void test() {try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUid(1);User user1 = mapper.select2(user);System.out.println(JSON.toJSONString(user1, true));} catch (IOException e) {e.printStackTrace();}
}
==> Preparing: select uid, uname, upassword, u_nickname from user where uid = ?
==> Parameters: 1(Integer)
<== Columns: uid, uname, upassword, u_nickname
<== Row: 1, 赵云, 123456, 常山赵子龙
<== Total: 1
{"uid":1,"uname":"赵云","unickname":"常山赵子龙","upassword":"123456"
}
9、MyBatis的动态SQL相关推荐
- MyBatis的动态SQL详解
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有: if choose(when,otherwis ...
- Mybatis解析动态sql原理分析
前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...
- MyBatis中动态sql实现时间范围比较的查询
场景 前端传递两个时间参数,开始时间和结束时间,然后从数据库中筛选出某个时间属性在此范围的数据. Mybatis的动态sql的写法. 注: 博客: https://blog.csdn.net/bada ...
- MyBatis中动态sql的模糊搜索、foreach实现In集合的用法
场景 在使用MyBatis的动态sql时,常见的是传递一个ID的数组,查询记录的 ID在这个数组中的记录和模糊搜索这两种场景. 注: 博客: https://blog.csdn.net/badao_l ...
- mybatis的动态sql的一些记录
动态sql的作用:传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if ...
- MyBatis(三)——动态SQL
文章目录 1. 简介 2. 搭建环境 2.1 在MySQL中创建blog表 2.2 编写实体类 2.3 编写实体类对应Mapper接口 2.4 编写Mapper接口对应的Mapper.xml文件 2. ...
- 9、mybatis中动态sql的使用
对于初学者,如何进行mybatis的学习呢?我总结了几点,会慢慢的更新出来.首先大家需要了解mybatis是什么.用mybatis来做什么.为什么要用mybatis.有什么优缺点:当知道了为什么的时候 ...
- 利用MyBatis的动态SQL特性抽象统一SQL查询接口
1. SQL查询的统一抽象 MyBatis制动动态SQL的构造,利用动态SQL和自定义的参数Bean抽象,可以将绝大部分SQL查询抽象为一个统一接口,查询参数使用一个自定义bean继承Map,使用映射 ...
- java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】...
第1章 Mybatis 连接池与事务深入 1.1 Mybatis 的连接池技术 1.1.1 Mybatis 连接池的分类 1.1.2 Mybatis 中数据源的配置 1.1.3 Mybatis 中 D ...
- 2022/5/1 Mybatis框架动态SQL
目录 1丶动态 SQL 2丶if标签 3丶choose.when.otherwise 4丶trim.where.set 5丶foreach 6丶script 7丶bind 8丶多数据库支持 9丶动态 ...
最新文章
- Visual Studio进行Web性能测试- Part III
- linux dd 截文件,Linux使用dd命令快速生成大文件(转)
- [WPF Bug清单]之(6)——Button的IsCancel属性失效
- mongodb系列~mongodb慢语句(2)
- oc40--类的启动过程
- Centos 7下查看当前目录大小及文件个数
- bootstraptable 汇总_bootstrap-table事件汇总
- java finally块_java finally块后的语句是否要执行
- Log4j 第三次发布漏洞补丁,漏洞或将长存
- Git fetch pull 详解
- 现在的00后都这么牛X的吗?
- 史上最奢华AirPods登场 售价直接翻四倍却还算良心
- vue ---- 动态组件
- html验证码功能如何实现原理,基于JS实现一个随机生成验证码功能
- 数学建模:现代优化算法之粒子群算法
- 计算机中英文打字文章,中英文混合打字文章
- f(!gotop.length) return false;
- V831基础-UART
- C#上位机系列(4)—示波器一新窗口的建立
- google AdView