MyBatis之动态SQL的使用
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 属性中指定的内容。
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<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片段
我们会将公共的部分提取出来,方便复用
使用:
- 使用SQL标签提取公共的部分
<!-- 将公共部分,需要重复使用的sql提取出来,使用sql标签-->
<sql id="if-titlt-author"><if test="title!=null">title=#{title},</if><if test="author!=null">and author=#{author}</if></sql>
- 在需要使用的地方使用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的使用相关推荐
- 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丶动态 ...
最新文章
- XAMPP维基百科,自由的百科全书
- SQL语言之DQL语言学习(七)分组查询
- 再谈矩阵分解在推荐系统中的应用
- RocketMQ的安装与启动
- python端口绑定错误怎么解决,python的 port binding error 请问怎么解决
- 基于simhash的短文本去重
- 【Spring Cloud sunX】中间件容器化部署
- 安装了vmWare15,打开虚拟机时,电脑总是重启,怎么办?
- 事件委托(事件代理)是什么?有什么用?
- UVP Phase运行机制的补充-Phase 的raise和drop机制
- 区块链中的“双花”问题
- Java实现png图片转pdf
- TEK-DPO2024示波器使用手册
- 自定义画圆进度条,带波浪动态效果
- Vue中$refs 使用详解
- 计算机专业的就业前景怎么样?
- 机器学习考点---过拟合与欠拟合、CNN原理......
- Mysql存储过程-新增数据时多条件判定是否已经存在某值
- byte和bit的区别,字节和比特,1兆等于多少字节,等于多少比特
- 西门子界面精美触摸屏+WINCC程序模板 西门子触摸屏程序模板