什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句.
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
-------------------------------
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
创建一个基础工程
1、导包
2、编写配置文件
3、编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
4、编写实体类对应的mapper接口和mapper.xml
//插入数据
int addBook(Blog blog);
<insert id="addBook" parameterType="blog">
insert into mybatis.blog(id, title, author, create_time, views)
values (#{id}, #{title}, #{author}, #{createTime}, #{views})
</insert>
5、测试
@Test
public void addInitBlog() {
SqlSession session = MybatisUtils.getSqlSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDUtils.getId());
blog.setTitle("Mybatis如此简单");
blog.setAuthor("zhy");
blog.setCreateTime(new Date());
blog.setViews(9999);
mapper.addBook(blog);
blog.setId(IDUtils.getId());
blog.setTitle("Java如此简单");
mapper.addBook(blog);
blog.setId(IDUtils.getId());
blog.setTitle("Spring如此简单");
mapper.addBook(blog);
blog.setId(IDUtils.getId());
blog.setTitle("微服务如此简单");
mapper.addBook(blog);
session.close();
}
if语句
List<Blog> queryBlogIf(Map map);
<select id="queryBlogIf" resultType="blog" parameterType="map">
select *
from mybatis.blog
where 1 = 1
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</select>
测试
@Test
public void quertBlogIf() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap<>();
// map.put("title", "Java如此简单");
map.put("author", "zhy");
List<Blog> blogs = mapper.queryBlogIf(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
choose (when, otherwise)
相当于switch…case语句
List<Blog> queryBlogChoose(Map map);
<select id="queryBlogChoose" resultType="blog" parameterType="map">
select *
from mybatis.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>
测试
@Test
public void quertBlogChoose() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap<>();
// map.put("title", "Java如此简单");
map.put("author", "狂神说");
map.put("views", 9999);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
trim (where, set)
where 元素只会在至少有一个子元素的条件返回SQL子句的情况下才去插入WHERE子句。而且,若语句的开头为AND’或OR ',where元素也会将它们去除。
当where标签内的if标签都失效时,会自动去掉where标签
where
select *
from mybatis.blog
<where>
<if test="title!=null">
and title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</where>
set 去逗号,当if标签内容为空时会去掉set标签产生语法错误
//更新博客
int updateBlog(Map map);
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title !=null">
title = #{title},
</if>
<if test="author !=null">
author = #{author}
</if>
where id = #{id}
</set>
</update>
测试
@Test
public void updateBlog() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap<>();
// map.put("title", "小明自黑");
map.put("author", "小张");
map.put("id", "16e3ab6be5d44e58a3898761b6e159c6");
mapper.updateBlog(map);
sqlSession.close();
}
SQL片段
将一些相同功能的代码抽取出来复用
1、使用SQL标签抽取公共的部分
<!--sql片段-->
<sql id="if-title-author">
<if test="title!=null">
title = #{title}
</if>
<if test="author!=null">
and author = #{author}
</if>
</sql>
2、在需要使用的地方使用include标签引用即可
<select id="queryBlogIf" resultType="blog" parameterType="map">
select *
from mybatis.blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
3、注意事项
● 最好基于单表定义SQL片段
● SQL片段不要存在where标签
foreach
总结,动态sql本质还是sql语句,只是我们可以在sql层面,去执行逻辑代码
批量新增,批量删除
//查询第1,2,3号记录的博客
List<Blog> queryBlogByForeach(Map map);
<!--
现在传递一个map ,给这个map传一个集合
-->
<select id="queryBlogByForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" separator="or" close=")">
id=#{id}
</foreach>
</where>
</select>
测试
@Test
public void quertBlogForeach() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap<>();
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
map.put("ids", ids);
List<Blog> blogs = mapper.queryBlogByForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,
去排列组合就可以了
● 建议:
○ ·现在Mysql中写出完整的SQL,再对应的去修改成为我们的动态SQL实现通用即可!
● 面试高频
○ Mysql引擎
○ lnnoDB底层原理
○ ·索引
○ 索引优化!