mybatis系列十:mybatis缓存机制

来源:互联网 发布:手机炒股什么软件 编辑:程序博客网 时间:2024/05/16 05:06

         MyBatis具有非常强大的查询缓存特性,它可以方便地配置和定制。缓存可以进行全局的配置,也可以针对映射语句进行配置。MyBatis的缓存分为一级缓存和二级缓存,一级缓存指的是在session  内,session没有关闭时,执行同样的SQL语句会使用的缓存。如果参数改变,缓存就会失效。而二级缓存可以被所有的SqlSession共享,下面指的是对二级缓存的配置。

    1.MyBatis的全局cache配置

全局的开关在MyBatis的配置文件中,默认是true。如果它配置成false,在Mapper XML中再配置支持cache也没有用。

   <settings>

      <setting name="cacheEnabled"value="true"/>

   </settings>

2.在Mapper XML文件中开启二级缓存

在Mapper XML文件中设置缓存,默认情况下是没有开启缓存的。

要开启二级缓存,需要在SQL映射文件中添加一行:

<catch/>

它将采用默认的行为进行缓存。可以通过修改缓存元素的属性进行定制,如:

<cacheeviction="FIFO" flushInterval="60000"

size="512" readOnly="true"/>

默认行为如下:

Ø  映射语句文件中的所有select语句的查询结果将会被缓存。

Ø  映射语句文件中的所有insert、update和delete语句会刷新缓存。

Ø  缓存会使用LeastRecently Used  (LRU,最近很少使用的)算法来回收。

Ø  只在语句调用时刷新缓存。

Ø  缓存会存储查询返回的列表集合或对象的1024个引用。

Ø  读写缓存,意味着查到的对象不是共享的,调用者可以放心地使用和修改,不会受到其他调用者或线程所做的潜在修改的干扰。

 

属性及其描述如下表所示:

属性名称描述eviction

可用资源的回收策略,主要包括以下几种:

LRU:较少使用的、移除最长时间不被使用的对象。

FIFO(先进先出):按对象进入缓存的顺序将其移除。

SOFT(软引用):移除基于垃圾回收器状态和软引用规则的对象。

WEAK(弱引用):积极地移除基于垃圾收集器状态和弱引用规则的对象。默认为LRUflushInterval刷新间隔,可以被设置为任意的正整数,它们代表一个合理的毫秒形式的时间段。
默认情况下不设置,即没有刷新间隔,缓存仅在调用语句时刷新size引用数目,可以被设置为任意正整数,要牢记缓存的对象数目和运行环境的可用内存资源数目。
默认值为1024readOnly只读属性可以被设置为true或false。只读的缓存设置会给所有调用者返回缓存对象的相同实例。
因此这些对象不能被修改。此处提供了很重要的性能优势。
可读写的缓存会返回缓存对象的拷贝(通过序列化)。
这样较为缓慢,但比较安全,因此默认为false

3.单独设置cache

在Mapper XML文件配置支持cache后,如果需要对个别查询进行调整,可以单独设置cache。

    <selectid="SelectAll"  resultType= "StudentEntity" useCache="true" >

select的useCache的默认值是true,一般情况下采用默认值。


4.  缓存演示案例

package com.obtk.test3;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.ibatis.session.SqlSession;import com.obtk.entitys.StudentEntity;import com.obtk.utils.MybatisUtil;public class TestCacheOne {public static void main(String[] args) {SqlSession session=null;try {//4.得到sessionsession=MybatisUtil.getSession();//5.执行语句List<StudentEntity> stuList=session.selectList("stu.selectByName", "王");for(StudentEntity stu : stuList){System.out.println(stu.getStuName()+","+stu.getGender());}System.out.println("============这是华丽的分割线=================");//重新执行,只有一个sql,说明默认利用一级缓存//MybatisUtil.closeSession();//session=MybatisUtil.getSession();stuList=session.selectList("stu.selectByName", "王");for(StudentEntity stu : stuList){System.out.println(stu.getStuName()+","+stu.getGender());}} catch (Exception e) {e.printStackTrace();}finally{MybatisUtil.closeSession();}}}
运行结果如下图所示:

只看到了一个sql语句输出,说明一级缓存起作用了

如果关闭session,再打开sesson,则运行结果如下图:

发现有两个sql输出,即查询了2次数据库。说明关闭了sesson之后,一级缓存失效了。

下面来看二级缓存的效果。

首先在核心配置文件里面开启二级缓存

=========================mybatis-config.xml====================

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"    "mybatis-3-config.dtd"><configuration>    <!-- 在核心配置文件里面开启二级缓存 -->    <settings><!-- 是否开启全局缓存 -->        <setting name="cacheEnabled" value="true"/>        <!-- 查询时,关闭关联对象即时加载以提高性能 -->        <setting name="lazyLoadingEnabled" value="false"/>        <!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->        <setting name="multipleResultSetsEnabled" value="true"/>        <!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能 -->        <setting name="aggressiveLazyLoading" value="true"/></settings></configuration>
然后在StudentMapper.xml中开启缓存。

<cache></cache>

==============================

package com.obtk.test3;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.ibatis.session.SqlSession;import com.obtk.entitys.StudentEntity;import com.obtk.utils.MybatisUtil;public class TestCacheTwo {public static void main(String[] args) {SqlSession session=null;try {//4.得到sessionsession=MybatisUtil.getSession();//5.执行语句List<StudentEntity> stuList=session.selectList("stu.selectByName", "王");for(StudentEntity stu : stuList){System.out.println(stu.getStuName()+","+stu.getGender());}//关闭sessionMybatisUtil.closeSession();session=MybatisUtil.getSession();stuList=session.selectList("stu.selectByName", "王");for(StudentEntity stu : stuList){System.out.println(stu.getStuName()+","+stu.getGender());}} catch (Exception e) {e.printStackTrace();}finally{MybatisUtil.closeSession();}}}
这时候session关闭了重新再打开,运行效果如下:

发现只有一个sql输出,并且缓存命中了。




原创粉丝点击