1、动态SQL

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

  1. 如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
  2. if
  3. choose (when, otherwise)
  4. trim (where, set)
  5. foreach

1.1、搭建环境

  1. create table blog(
  2. id varchar(50) not null comment '博客id',
  3. title varchar(100) not null comment '博客标题',
  4. author varchar(30) not null comment '博客作者',
  5. create_time datetime not null comment '创建时间',
  6. views int(30) not null comment '浏览量'
  7. );

创建一个基本工程

  1. 导包
  2. 编写配置文件
  3. 编写实体类
  4. 编写实体类对应的Mapper接口 和 Mapper.xml文件

1.2、IF

  1. <select id="queryBlogIF" parameterType="map" resultType="blog">
  2. select * from blog where 1=1
  3. <if test="title != null">
  4. and title = #{title}
  5. </if>
  6. <if test="author != null">
  7. and author = #{author}
  8. </if>
  9. </select>
  1. <select id="queryBlogIF2" parameterType="map" resultType="Blog">
  2. select * from blog
  3. <where>
  4. <if test="title != null">
  5. title = #{title}
  6. </if>
  7. <if test="author != null">
  8. and author = #{author}
  9. </if>
  10. </where>
  11. </select>

1.3、choose(when,otherwise)

  1. <where>
  2. <choose>
  3. <when test="title != null">
  4. title = #{title}
  5. </when>
  6. <when test="author != null">
  7. and author = #{author}
  8. </when>
  9. <otherwise>
  10. and views = #{views}
  11. </otherwise>
  12. </choose>
  13. </where>

1.4、trim(where,set)

  1. update blog
  2. <set>
  3. <if test="title != null">
  4. title = #{title},
  5. </if>
  6. <if test="author != null">
  7. author = #{author}
  8. </if>
  9. </set>
  10. where id = #{id}

补充:https://www.jianshu.com/p/d27f60937da9

所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码

1.5、SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用SQL标签抽取公共的部分
    1. <sql id="if-title-author">
    2. <if test="title != null">
    3. title = #{title}
    4. </if>
    5. <if test="author != null">
    6. author = #{author}
    7. </if>
    8. </sql>
  1. 在需要使用的地方使用Include标签引用即可
    1. <select id="queryBlogIF" parameterType="map" resultType="blog">
    2. select * from blog where
    3. <include refid="if-title-author"></include>
    4. </select>

注意事项:

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

1.6、Foreach

  1. <!--select * from blog where 1=1 and (id=1 or id=2 or id=3)
  2. 我们现在传递一个万能的map, 这map中可以存在一个集合!
  3. -->
  4. <select id="queryBlogForeach" parameterType="map" resultType="blog">
  5. select * from blog
  6. <where>
  7. <foreach collection="ids" item="id" open="(" close=")" separator="or">
  8. id = #{id}
  9. </foreach>
  10. </where>
  11. </select>

2、缓存

2.1、简介

  1. 什么是缓存【Cache】?
    • 存在内存中的临时数据
    • 将用户经常查询的数据存放到缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
  2. 为什么使用缓存?
    • 减少和数据库的交互次数,减少系统开销,提高系统效率。
  3. 什么样的数据能使用缓存?
    • 经常查询并且不经常改变的数据。

2.2、Mybatis缓存

  • Mybatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提高查询效率。
  • Mybatis系统中默认定义了两级缓存:一级缓存二级缓存
    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存。
    • 为了提高扩展性,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

2.3、一级缓存

  • 一级缓存也叫本地缓存: SqlSession
    • 与数据库同一次会话期间查询到的数据会放在本地缓存中。
    • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;

测试步骤:

  1. 开启日志!
  2. 测试在一个Session中查询两次相同记录
  3. 查看日志输出

缓存失效的情况:

  1. 查询不同的东西
  2. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存!
  3. 查询不同的Mapper.xml
  4. 手动清理缓存!
    1. sqlSession.clearCache(); // 手动清除缓存

小结:一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间段!

一级缓存就是一个Map。

2.4、二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    • 新的会话查询信息,就可以从二级缓存中获取内容;
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

步骤:

  1. 开启全局缓存
    1. <!--显示的开启全局缓存 ,默认是开启的-->
    2. <setting name="cacheEnabled" value="true"/>
  1. 在要使用二级缓存中的Mapper中开启

    1. <!--在当前的Mapper.xml中使用二级缓存-->
    2. <cache/>


    也可以自定义参数

  2. 测试

    1. 问题:我们需要将实体类序列化!否则就会报错!
      1. Cause: java.io.NotSerializableException: com.shuai.pojo.User

      需要在实体类实现Serializable接口

小结:

  • 只要开启了二级缓存,在同一个Mapper下就有效
  • 所有的数据都会先放在一级缓存中;
  • 只有当会话提交,或者关闭的时候,才会提交到二级缓存中!
  • 缓存顺序
    • 先看二级缓存中有没有
    • 再看一级缓存中有没有
    • 最后再查询数据库