MyBatis之动态SQL的使用

什么是动态SQL:简单来说就是根据不同的的条件生成不同的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

数据库准备,创建一个blok的表

create table blog(id int primary key comment '博客id',title varchar(100) not null comment '博客标题',author varchar(30) not null comment '博客作者',create_time varchar(50) not null comment '创建时间',views int(30) not null comment '浏览量'
) insert into blog values(1,'javaWeb教程','黑马程序员',now(),1000)
insert into blog values(2,'安卓软件开发','周世凯,陈小龙',now(),1000)
insert into blog values(3,'数据结构','清华大学出版社',now(),10000)
insert into blog values(4,'人文基础与应用','毛灿月',now(),560)
insert into blog values(5,'java教程','小钱',now(),123456)
insert into blog values(6,'C语言','谭浩强',now(),10000)
insert into blog values(7,'C语言','小毛',now(),10000)

编写实体类

@Data
public class Blog {private int id;private String title;private String author;private String  create_Time;private int views;
}

1、if语句

编写接口

//    通过if,查询博客List<Blog> queryBlogIF(Map map);

编写Mapper.xml的sql语句

    <select id="queryBlogIF" parameterType="map" resultType="pojo.Blog">select * from blog<where><if test="title!=null">and title=#{title}</if><if test="author!=null">and author=#{author}</if></where></select>

如果不传入 “title”,那么所有的 Blog 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行查找并返回对应的 Blog结果

where标签会在下面介绍

测试类

    @Testpublic void queryBlogIF(){SqlSession sqlSession = Mybatisutil.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();map.put("title","C语言");map.put("author","谭浩强");List<Blog> blogs = mapper.queryBlogIF(map);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();}

结果

2、choose、when、otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

编写接口

   //    通过choose,查询博客List<Blog> queryBlogChoose(Map map);

编写Mapper.xml的sql语句

   <select id="queryBlogChoose" parameterType="map" resultType="pojo.Blog">select * from blog<where><choose><when test="title!=null">title=#{title}</when><when test="author!=null">and author=#{author}</when><otherwise>and views=#{views}</otherwise></choose></where></select>

测试类

    //通过choose查询@Testpublic void queryBlogChoose(){SqlSession sqlSession = Mybatisutil.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();map.put("title","C语言");map.put("author","谭浩强");List<Blog> blogs = mapper.queryBlogChoose(map);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();}

结果

当title满足要求时,即’break‘退出choose选择,就不会执行下面sql语句的拼接,和switch一样,所以这里查出来的有两条记录,当我只传入views参数时候,就会拼接 otherwise标签的语句,结果如下

3、trim、where、set

在我们拼接语句的时候,会有标点符号,前缀后缀符号等问题,这个时候可以用trim来解决。

如下面的sql语句,假如没有使用where标签,那么如果if语句中没有满足条件的拼接语句,这个时候我们的sql语句就是select * from blog where,这样的sql语句就是错误的,那么where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

    <select id="queryBlogIF" parameterType="map" resultType="pojo.Blog">select * from blogwhere<if test="title!=null">and title=#{title}</if><if test="author!=null">and author=#{author}</if></select>

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR ">...
</trim>

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:

<update id="updateAuthorIfNecessary">update Author<set><if test="username != null">username=#{username},</if><if test="password != null">password=#{password},</if><if test="email != null">email=#{email},</if><if test="bio != null">bio=#{bio}</if></set>where id=#{id}
</update>

这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

来看看与 set 元素等价的自定义 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">...
</trim>

3.1、set修改数据

编写接口

    //使用set修改数据int updateBlog(Map map);

编写Mapper.xml的sql语句

<update id="updateBlog" parameterType="map">update blog<set><if test="title!=null">title=#{title},</if><if test="author!=null">author=#{author}</if></set>where id=#{id}</update>

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

测试类

    @Testpublic void updateBlog(){SqlSession sqlSession = Mybatisutil.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();//map.put("title","C语言");map.put("author","小浩强");map.put("id",6);mapper.updateBlog(map);sqlSession.close();}

结果

4、Foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历

编写接口

  //使用foreach查询3 4 5 条博客List<Blog> queryBlogForeach(Map map);

编写Mapper.xml的sql语句

    <select id="queryBlogForeach" parameterType="map" resultType="pojo.Blog">select * from blog<where><foreach collection="ids" item="id" open="and (" close=")" separator="or">id=#{id}</foreach></where></select>

测试类

    @Testpublic void queryBlogForeach(){SqlSession sqlSession = Mybatisutil.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);HashMap map = new HashMap();ArrayList<Integer> idlist = new ArrayList<>();idlist.add(3);idlist.add(4);idlist.add(5);map.put("idlist",idlist);List<Blog> blogs = mapper.queryBlogForeach(map);for (Blog blog : blogs) {System.out.println(blog);}sqlSession.close();}

结果:

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

5、SQL片段

我们会将公共的部分提取出来,方便复用

使用:

  1. 使用SQL标签提取公共的部分
<!--    将公共部分,需要重复使用的sql提取出来,使用sql标签-->
<sql id="if-titlt-author"><if test="title!=null">title=#{title},</if><if test="author!=null">and author=#{author}</if></sql>
  1. 在需要使用的地方使用include标签
<!--    在需要使用的地方使用include标签--><select id="queryBlogIF" parameterType="map" resultType="pojo.Blog">select * from blog<where><include refid="if-titlt-author"></include></where></select>

注意事项:

  • 最好基于单表来定义SQL片段
  • 不要存在where标签

总结:

  • 动态SQl就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列就行
  • 书写sql语句之前先在sql查询环境中测试一下,避免写错,在编写Mappre.xml的时候找BUG。

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. XAMPP维基百科,自由的百科全书
  2. SQL语言之DQL语言学习(七)分组查询
  3. 再谈矩阵分解在推荐系统中的应用
  4. RocketMQ的安装与启动
  5. python端口绑定错误怎么解决,python的 port binding error 请问怎么解决
  6. 基于simhash的短文本去重
  7. 【Spring Cloud sunX】中间件容器化部署
  8. 安装了vmWare15,打开虚拟机时,电脑总是重启,怎么办?
  9. 事件委托(事件代理)是什么?有什么用?
  10. UVP Phase运行机制的补充-Phase 的raise和drop机制
  11. 区块链中的“双花”问题
  12. Java实现png图片转pdf
  13. TEK-DPO2024示波器使用手册
  14. 自定义画圆进度条,带波浪动态效果
  15. Vue中$refs 使用详解
  16. 计算机专业的就业前景怎么样?
  17. 机器学习考点---过拟合与欠拟合、CNN原理......
  18. Mysql存储过程-新增数据时多条件判定是否已经存在某值
  19. byte和bit的区别,字节和比特,1兆等于多少字节,等于多少比特
  20. 西门子界面精美触摸屏+WINCC程序模板 西门子触摸屏程序模板

热门文章

  1. python+gdal+numpy计算ndvi
  2. ffmpeg视频剪辑视频长度问题,视频无声音,视频卡顿问题
  3. 什么是溢出?补码加法运算如何判断是否溢出?
  4. MyBatis学习总结-06:动态SQL
  5. 手机百度云如何打开doc
  6. 本安计算机电缆执行标准,阻燃本安计算机信号电缆ZR-IA-DJYPVRP-1*2*1.5
  7. 植物大战僵尸存档关卡和金币修改
  8. Python复合梯形公式计算
  9. HDU 6438 Buy and Resell (优先队列 or 贪心)
  10. 《初等数论及其应用》第三章 素数和最大公因子