mybatis系列十:mybatis缓存机制

         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映射文件中添加一行:

<cache/>

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

<cache eviction="FIFO" flushInterval="60000"

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

默认行为如下:

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

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

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

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

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

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

 

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

属性名称描述
eviction

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

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

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

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

WEAK(弱引用):积极地移除基于垃圾收集器状态和弱引用规则的对象。默认为LRU
flushInterval刷新间隔,可以被设置为任意的正整数,它们代表一个合理的毫秒形式的时间段。
默认情况下不设置,即没有刷新间隔,缓存仅在调用语句时刷新
size引用数目,可以被设置为任意正整数,要牢记缓存的对象数目和运行环境的可用内存资源数目。
默认值为1024
readOnly只读属性可以被设置为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.得到session
			session=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.得到session
			session=MybatisUtil.getSession();
			//5.执行语句
			List<StudentEntity> stuList=session.selectList("stu.selectByName", "王");
			for(StudentEntity stu : stuList){
				System.out.println(stu.getStuName()+","+stu.getGender());
			}
			//关闭session
			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();
		}
	}
}
这时候session关闭了重新再打开,运行效果如下:

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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御前两把刀刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值