目录
2.Mybatis第二篇| CRUD,这才是程序员入门第一课
3.Mybatis第三篇| Mybatis配置,有点小个性!
4.Mybatis第四篇| 类处理器什么玩意?举个栗子你就知道了
前言
今天我们来学习一下动态sql,看起来很NB的感觉。我们来看看官网是怎么来介绍动态sql的。
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
简而言之,就是可以根据不同的条件自动给我们生产sql语句。废话不多说,我们看看到底是怎么操作的。
动态sql
虽然官方文档说这个特性很牛逼,但是还有一句话我们没看到:
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
也就是说我们还是需要去学习动态sql语句的语法。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
动态语句其实也就上面的四个标签语句,用过xml的或者JSTL等文本处理语言的同学可能很快就能理解。
我们这次来重新创建一个SQL表,来进行我们这次的演示,建表语句放在下面:
CREATE TABLE `bolg`( `id` VARCHAR(50) NOT NULL COMMENT '博客id', `title` VARCHAR(100) not null comment '博客标题', `author` VARCHAR(30) not null comment '博客作者', `create_time` datetime not null comment '创建时间', `views` int(30) not null comment '浏览量' )ENGINE=InnoDB DEFAULT CHARSET=utf8
大家可以自己插入几条数据,下面是我在该表插入的数据:
if
首先在dao层创建我们的BlogMapper接口类:
public interface BlogMapper { List<Blog> queryBlogIF(Map map); List<Blog> queryBlogWhere(Map map); List<Blog> queryBlogChoose(Map map); int updateBlog(Map map); List<Blog> queryBlogForeach(Map map); }
创建以上几个接口。
首先我们来看下if语句是怎么玩的:
<select id="queryBlogIF" parameterType="map" resultType="Blog"> select * from blog where 1=1 <if test="title != null"> and title = #{title} </if> <if test="author != null"> and author = #{author} </if> </select>
if的语法就是
<if test="判断条件"> </if>
上面的判断条件就是如果title不等于null,那么就根据title来查询,如果author不等于null,那么就根据author来查询,如果两者都不等于null,那么就根据他们两者来进行查询。
我们再test中写一个简单的测试类:
@Test public void queryBlogIF(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); map.put("title","编程如此简单2"); map.put("author","kuls"); List<Blog> blogs = mapper.queryBlogIF(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
查询出来的结果
where
<select id="queryBlogIF" parameterType="map" resultType="Blog"> select * from blog where 1=1 <if test="title != null"> and title = #{title} </if> <if test="author != null"> and author = #{author} </if> </select>
大家可能看到我在上面的where语句中含有 1=1 ,原因是如果我们不写一个where语句在前面,这条sql就会变成这样
select * from blog where and title = #{title}
这明显是错误的,当然1=1的写法也并不是很好,那怎么解决这个问题呢?mybatis也提供了一个< where >标签给我们使用。
我们将上面的语句改成下面的即可:
<select id="queryBlogWhere" parameterType="map" resultType="blog"> select * from blog <where> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </where> </select>
我们通过一个简单的测试类来看看他的运行结果:
@Test public void queryBlogWhere(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); map.put("title","编程如此简单2"); List<Blog> blogs = mapper.queryBlogWhere(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
我们可以看到,通过where标签拼接成的语句变成了一条完整的sql语句(这里能够显示完整的sql语句是因为我使用了日志功能,这个功能我会在下一篇文章中介绍):
choose (when, otherwise)
<select id="queryBlogIF" parameterType="map" resultType="Blog"> select * from blog where 1=1 <if test="title != null"> and title = #{title} </if> <if test="author != null"> and author = #{author} </if> </select>
还是回归到学习if时候的那句sql,如果我们有一个需求是满足title和author一个条件时就就够了情况时候,我们该怎么写呢?也就是从多个条件里我们只需要一个条件满足。mybatis也给我们提供了相应的标签:
<select id="queryBlogChoose" parameterType="map" resultType="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>
其实这个语句跟我们的switch case语句非常相似,otherwise则是default。由于这个比较简单,我这里就不做演示了。
set
set语句也就比较简单了,直接上代码:
<update id="updateBlog" parameterType="map"> update blog <set> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </set> where id = #{id} </update>
set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
trim
这个标签可能有一部分同学不太理解,其实where标签能够自动帮我们去除AND,就是依靠trim标签实现的。我们也可以直接使用trim的方式来实现where的效果:
<select id="queryBlogWhere" parameterType="map" resultType="blog"> select * from blog <trim prefix="WHERE" prefixOverrides="AND"> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </trim> </select>
使用trim,prefixOverrides 属性中指定的内容会被自动清除,然后填充为prefix中的内容。除了prefix前缀,我们也可以设置suffix后缀。
foreach
大家看名字应该大概理解是啥意思,其实就是对集合进行遍历的一个操作,例如我们根据一个id集合来查询相应id的内容。
<select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <foreach collection="ids" item="id" open="(" close=")" separator="or"> id = #{id} </foreach> </where> </select>
大家先不用管理不理解上面的代码,我们先来进行测试:
@Test public void queryBlogForeach(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); //创建一个id集合 ArrayList<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(2); ids.add(3); map.put("ids",ids); //查询这个ids集合对应的内容 List<Blog> blogs = mapper.queryBlogForeach(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
我们输出时,可以看到日志中输出的内容
大家可以看到,mybatis给我们自动拼接了sql语句
select * from mybatis.blog WHERE ( id = ? or id = ? or id = ? )
这样的话,我们也就能过理解foreach中的属性了
<foreach collection="ids" item="id" open="(" close=")" separator="or"> id = #{id} </foreach>
- collection是需要查询的集合
- item集合中的每个属性
- open 查询集合的前缀标签
- close 查询集合的后缀标签
- separator 分隔符
本文代码
完整代码:
https://github.com/hellokuls/kuls-mybatis
之后该系列的代码和文章
全部放在这个GitHub项目,欢迎大家star!