文章目录

  • 动态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相关推荐

  1. MyBatis的动态SQL详解

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有:   if choose(when,otherwis ...

  2. Mybatis解析动态sql原理分析

    前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...

  3. MyBatis中动态sql实现时间范围比较的查询

    场景 前端传递两个时间参数,开始时间和结束时间,然后从数据库中筛选出某个时间属性在此范围的数据. Mybatis的动态sql的写法. 注: 博客: https://blog.csdn.net/bada ...

  4. MyBatis中动态sql的模糊搜索、foreach实现In集合的用法

    场景 在使用MyBatis的动态sql时,常见的是传递一个ID的数组,查询记录的 ID在这个数组中的记录和模糊搜索这两种场景. 注: 博客: https://blog.csdn.net/badao_l ...

  5. mybatis的动态sql的一些记录

    动态sql的作用:传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if ...

  6. MyBatis(三)——动态SQL

    文章目录 1. 简介 2. 搭建环境 2.1 在MySQL中创建blog表 2.2 编写实体类 2.3 编写实体类对应Mapper接口 2.4 编写Mapper接口对应的Mapper.xml文件 2. ...

  7. 9、mybatis中动态sql的使用

    对于初学者,如何进行mybatis的学习呢?我总结了几点,会慢慢的更新出来.首先大家需要了解mybatis是什么.用mybatis来做什么.为什么要用mybatis.有什么优缺点:当知道了为什么的时候 ...

  8. 利用MyBatis的动态SQL特性抽象统一SQL查询接口

    1. SQL查询的统一抽象 MyBatis制动动态SQL的构造,利用动态SQL和自定义的参数Bean抽象,可以将绝大部分SQL查询抽象为一个统一接口,查询参数使用一个自定义bean继承Map,使用映射 ...

  9. 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 ...

  10. 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丶动态 ...

最新文章

  1. Visual Studio进行Web性能测试- Part III
  2. linux dd 截文件,Linux使用dd命令快速生成大文件(转)
  3. [WPF Bug清单]之(6)——Button的IsCancel属性失效
  4. mongodb系列~mongodb慢语句(2)
  5. oc40--类的启动过程
  6. Centos 7下查看当前目录大小及文件个数
  7. bootstraptable 汇总_bootstrap-table事件汇总
  8. java finally块_java finally块后的语句是否要执行
  9. Log4j 第三次发布漏洞补丁,漏洞或将长存
  10. Git fetch pull 详解
  11. 现在的00后都这么牛X的吗?
  12. 史上最奢华AirPods登场 售价直接翻四倍却还算良心
  13. vue ---- 动态组件
  14. html验证码功能如何实现原理,基于JS实现一个随机生成验证码功能
  15. 数学建模:现代优化算法之粒子群算法
  16. 计算机中英文打字文章,中英文混合打字文章
  17. f(!gotop.length) return false;
  18. V831基础-UART
  19. C#上位机系列(4)—示波器一新窗口的建立
  20. google AdView

热门文章

  1. 关于各种职业的英文单词zz
  2. Python 类变量,成员变量,静态变量,局部变量
  3. HTTP和RTSP简介
  4. 宁波诺丁汉计算机博士学费,宁诺1600万元博士奖学金开放申请 PhD scholarships open for application...
  5. 【LeetCode】1818. 绝对差值和
  6. 如何把图片制作生成网站连接(URL)
  7. M3U8格式视频下载
  8. 施工建设企业为什么要使用智慧工地数管理系统?
  9. Java操作Word转PDF(Word转图片)
  10. 雷达成像原理(一)合成孔径成像Chirp-Scaling