什么是动态SQL?
动态 SQL 是 MyBatis 的强大特性之一。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
基础工程:
1、创建sql
CREATE TABLE `blog`( `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
2、导包
3、创建pojo实体类
@Data @AllArgsConstructor @NoArgsConstructor public class Blog { private int id; private String title; private String author; private Date create_time; private int views; }
4、编写实体类对应mapper接口 和 mapper.xml文件
=========================测试====================================
Where、if
提供了可选的查找文本功能。
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。
而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
<select id="selBlogIf" resultType="blog" parameterType="map">
/*1=1是为了让if为false的情况下能把所有的记录查出来*/
select * from blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
@Test public void selBlogIfTest(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map map = new HashMap(); map.put("title","Java"); List<Blog> blogs = mapper.selBlogIf(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
添加了title的值,说明上面发判断为true,就能查出来:title = "java"的记录
choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
- 匹配顺序是从第一个进行选择,第一个成立就执行第一个中的匹配,
- 如果第一个第二个数据都匹配的话,还是按第一个中的执行
- 所有条件不匹配就会执行otherwise
<select id="selBlogIf" resultType="blog" parameterType="map"> select * from blog <where> <choose> <when test="author != null"> and author = #{author} </when> <when test="title != null"> and title = #{title} </when> <otherwise> and views = #{views} </otherwise> </choose> </where> </select>
where、set
- set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
<update id="updateBlog" parameterType="map"> update blog <set> <if test="author != null"> author = #{author} </if> </set> <where> <if test="id != null"> id = #{id} </if> </where> </update>
@Test public void updateBlogIfTest(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map map = new HashMap(); map.put("id","4bdfaea75d5c416fb2c10a6d4c51cf8f"); map.put("author","zhangzhixi"); mapper.updateBlog(map); sqlSession.commit(); sqlSession.close(); }
修改成功!
SQL片段:
将需要的代码抽取出来,实现代码复用
1、使用sql标签抽取公共部分
2、使用include标签进行引入即可
<sql id="title_author"> <if test="title != null"> and title = #{title} </if> <if test="author != null"> and title = #{author} </if> </sql> <select id="conditionQuery" resultType="blog" parameterType="map"> select * from blog <where> <include refid="title_author"></include> </where> </select>
@Test public void conditionQueryTest(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map map = new HashMap(); map.put("title","Java"); List<Blog> blogs = mapper.conditionQuery(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
通过测试!查询到的结果跟if嵌套在where中的结果是一样的
注意事项:
1、最好基于单表来定义sql片段
2、sql片段中不要存在where标签