mybatis学习(十)——缓存介绍

与Hibernate一样,MyBatis 也提供了一级缓存和二级缓存的支持。

1、一级缓存:(本地缓存)SqlSession级别的缓存,默认一直开启的 ,

                 与数据库同一次会话期间的数据会放到本地缓存中,以后如果需要相同的数据,直接从缓存中拿,不再查询数据库。

                 当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。

    当进行增删改之后,该Session中的所有 Cache 就将清空。

2、二级缓存:基于namespace级别的缓存,一个namespace对应一个二级缓存

    可自定义存储源,如 Ehcache。

    当 Session flush 或 close 之后,二级缓存仍然可用。

    当进行增删改之后,该namespace的所有 Cache 就将清空。

    <setting name="cacheEnabled" value="false" />可关闭二级缓存,一级缓存可用。

一、一级缓存

package com.pjf.mybatis;

import java.io.IOException;
import java.io.InputStream;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.pjf.mybatis.dao.HotelMapper;
import com.pjf.mybatis.po.Hotel;

public class TestHotel {

    public SqlSessionFactory sqlSessionFactory() throws IOException {
        String resource = "mybatis_config.xml";
        InputStream is = Resources.getResourceAsStream(resource);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
        return sessionFactory;
    }
    /*
     * Mybatis缓存机制 
     *     一级缓存:(本地缓存)SqlSession级别的缓存,默认一直开启的 
     *             与数据库同一次会话期间的数据会放到本地缓存中
     *             以后如果需要相同的数据,直接从缓存中拿,不再查询数据库
     *          一级缓存的失效情况(需要重新发送sql)
     *            1、sqlSession不同
     *            2、sqlSession相同,查询条件不同
     *            3、sqlSession相同,查询条件相同,但两次查询之间执行了增删改操作
     *            4、sqlSession相同,查询条件相同,手动清除了缓存clearCache()
     */

    @Test
    public void testMybatisCache() throws IOException {

        SqlSessionFactory sessionFactory = sqlSessionFactory();
        SqlSession session = sessionFactory.openSession(true);
        HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
        Hotel hotel = hotelMapper.getHotel(1001);
        System.out.println(hotel);
        //第二次查询,条件一致
        Hotel hotel2 = hotelMapper.getHotel(1001);
        System.out.println(hotel2);
        session.close();
    }
}

一级缓存在以下四种情况下会失效

1、sqlSession不同
2、sqlSession相同,查询条件不同
3、sqlSession相同,查询条件相同,但两次查询之间执行了增删改操作
4、sqlSession相同,查询条件相同,手动清除了缓存clearCache()

二、二级缓存

修改HotalMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.pjf.mybatis.dao.HotelMapper">    
    <!-- cache   缓存开启
         eviction 缓存回售策略
                LRU 最近最少使用的,移除最长时间不被使用的(默认)
                FIFO 先进先出
                SOFT 软引用
                WEAK 弱引用
         flushInterval 缓存刷新间隔
                 缓存清空时间,默认不清空,设置毫秒值
         readOnly 缓存是否只读
                 true  mybatis只从缓存中毒数据,不会修改数据
                 false  mybatis认为缓存中的数据会被修改,会用序列化和反序列化技术克隆一份给用户,安全,速度慢
         size  缓存存放多少元素
         type  指定自定义缓存的全类名
     -->
    <cache eviction="LRU" flushInterval="60000" readOnly="false" size="1024" ></cache>
    
    <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
        <result column="hotel_address" property="hotelAddress"jdbcType="VARCHAR" />
        <result column="price" property="price" jdbcType="INTEGER" />
    </resultMap>

    <select id="getHotel"  resultMap="myHotel">
        select* 
        from hotel where id =#{id}
    </select>
</mapper>

测试类

package com.pjf.mybatis;

import java.io.IOException;
import java.io.InputStream;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.pjf.mybatis.dao.HotelMapper;
import com.pjf.mybatis.po.Hotel;

public class TestHotel {

    public SqlSessionFactory sqlSessionFactory() throws IOException {
        String resource = "mybatis_config.xml";
        InputStream is = Resources.getResourceAsStream(resource);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
        return sessionFactory;
    }
    /*
     *  二级缓存:基于namespace级别的缓存,一个namespace对应一个二级缓存
     *         工作机制:
     *             1、一个会话查询一个数据,这个数据会被保存到当前会话的一级缓存中
     *             2、如果会话关闭,一级缓存中的数据会被保存到二级缓存中,新的会话消息,就可以查询二级缓存
     *             3、不同namespace查出来的数据,会被放在自己对应的缓存中
     *         使用:
     *             1、开启全局二级缓存配置   <setting name="cacheEnabled" value="true" />
     *             2、去mapper.xml配置使用二级缓存      <cache></cache>
     *             3、pojo需要实现序列化接口
     */
    @Test
    public void testMybatisCache() throws IOException {

        SqlSessionFactory sessionFactory = sqlSessionFactory();
        SqlSession session = sessionFactory.openSession(true);
        HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
        Hotel hotel = hotelMapper.getHotel(1001);
        System.out.println(hotel);    
        //关闭第一次会话
        session.close();
        //第二次查询
        SqlSession session2 = sessionFactory.openSession(true);
        HotelMapper hotelMapper2 =session2.getMapper(HotelMapper.class);
        Hotel hotel2 = hotelMapper2.getHotel(1001);
        System.out.println(hotel2);
        session2.close();    
    }
}

二级缓存使用的时候主要有三步:

1、开启全局二级缓存配置   <setting name="cacheEnabled" value="true" />
2、去mapper.xml配置使用二级缓存      <cache></cache>
3、pojo需要实现序列化接口
原文地址:https://www.cnblogs.com/pjfmeng/p/7723580.html