Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件

MyBatis

  今天大年初一,你在学习!不学习做什么,斗地主...人都凑不齐。学习吧,学习使我快乐!除了诗和远方还有责任,我也想担当,我也想负责,可臣妾做不到啊,怎么办?你说怎么办,为啥人家能做到你做不到,因为人家比你多做了那么一点点。哪一点点?就那么一点点,只要你也多做那么一点点,不就做到了!...就那么一点点呀,我回顾SE去了。万丈高楼平地起,基础打的牢,怕什么狂风暴雨

MyBatis 动态SQL

  MyBatis为了解决通过一些不确定性的条件进行SQL语句的拼接操作的问题, 提供了动态SQL. 具体来说,就是提供了一些标签 等.写出可扩展SQL语句

  MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作

  OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。 类似于EL表达式,例:

    访问对象属性:              person.name

    调用方法:                     person.getName()

    调用静态属性/方法:     @java.lang.Math@PI    

    调用构造方法:              new com.bean.Person(‘admin’).name

    运算符:                         +,-*,/,%

    逻辑运算符:                  in,not in,>,>=,<,<=,==,!=

    注意:xml中特殊符号如”,>,<等这些都需要使用转义字符

 标签

   1) 用于完成简单的判断.只有一个属性 test 用于判断条件是否成立

   2) 在SQL语句中添加WHERE关键字, 作用:去掉 where 后面第一个条件前面的 and / or 。

    <select id="getBook" resultType="main.beans.Book">
        SELECT id,title,author,price
        FROM books
        <where>
            <if test="id != null"> and id= #{id}if>
            <if test="title != null"> and title = #{title}if>
        where>
    select>

   3)  : 可以在条件判断完的SQL语句的前后 添加内容 或者去掉指定的内容. 去掉第一个或最后一个

    prefix: 添加前缀  prefixOverrides: 去掉前缀

    suffix: 添加后缀  suffixOverrides: 去掉后缀

    <delete id="deleteBook">
        DELETE FROM books
        <trim prefix="WHERE" suffixOverrides="and">
            <if test="id != null">id = #{id} andif>
            <if test="title != null">itle = #{title} andif>
        trim >
    delete>

   4)   :在修改的操作中, 去掉SQL语句中多出的逗号,即在sql语句中最后句可能多出的逗号

    <update id="updateBook">
        UPDATE books
        <set>
            <if test="title != null">title = #{title},if>
            <if test="author != null">author = #{author},if>
        set>
        where id = #{id}
    update>

  5)  标签是用于抽取可重用的sql片段,将使用频繁的SQL片段抽取出来,不仅仅只提取整条sql语句,字段也可以提取

    id:指定被提取的 sql 片段唯一标识被引用

    引用:在任何需要插入此 sql 片段的语句中使用  引入即可

    <sql id="bookFields">
        id,title,author,price,sales,stock,img_path
    sql>
    <insert id="insertBook" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO books (<include refid="bookFields">include>)
        VALUES(#{id},#{title},#{author},#{price},#{sales},#{stock},#{imgPath})
    insert>

  6)   : 用于分支判断,最终只会满足其中的一个分支.  类似于 switch case 语句. 

    <select id="selectBookPrice" resultType="main.beans.Book">
        SELECT <include refid="bookFields">include>
        FROM books
        <where>
            <choose>
                <when test="id != null">id = #{id}when>
                <otherwise>price > #{price}otherwise>
            choose>
        where>
    select>

  7) : 主要用于循环迭代

      collection: 要迭代的集合

      item: 当前从集合中迭代出的元素赋值的变量

      open: 开始字符

      close:结束字符

      separator: 指定元素与元素之间的分隔符

      index:

        迭代的是List集合: index表示当前元素的下标

        迭代的Map集合:  index表示当前元素的 key

  注意:此操作属于批量操作需在 properties 配置的 url 中添加 allowMultiQueries=true 开启批处理

    <select id="getBooks" resultType="main.beans.Book">
        SELECT <include refid="bookFields">include>
        FROM books where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")" >
            #{id}
        foreach>
    select>

MyBatis 缓存机制

    MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率

    MyBatis系统中默认定义了两级缓存:一级缓存、二级缓存

    默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。

    二级缓存需要手动开启和配置,他是基于namespace级别的缓存。为了提高扩展性。MyBatis定义了缓存接口Cache,支持第三方缓存。

一级缓存

  1) 一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。每个sqlSession对象都有自己的一级缓存,相互独立不共享。当  Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空。

  2) 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域.

  3) 在mybatis3.1之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置

  4) 一级缓存的工作机制,同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中

     key: hashCode+查询的SqlId+编写的sql查询语句+参数

缓存机制:

  基于相同sqlSession多次查询,每次查询都会先从缓存中获取数据,如果缓存中没获取到数据,则从数据库中获取数据,之后,将数据存放到一级缓存。

一级缓存的失效问题

  1)不同的SqlSession对应不同的一级缓存

  2)同一个SqlSession但是查询条件不同

  3)同一个SqlSession两次查询期间执行了任何一次增删改操作
    增删改操作,会默认清空缓存。

  4)同一个SqlSession两次查询期间手动清空了缓存

总结:当同一 SqlSession 多次查询同一语句时,且中间未有增删改或手动刷新、关闭、清空 clearCache() 过缓存,便会直接从缓存中取数据。若开启了二级缓存则会先从二级缓存读取,若二级缓存里没有再去一级缓存读取,如果只想从一级缓存中读取可在对应