MyBatis数据缓存

为了提升查询效率,提高用户体验,MyBatis提供了数据缓存支持,依据数据缓存的有效范围默认定义了一级缓存和二级缓存
一级缓存
1、该级缓存默认开启,不能关闭;
2、该级缓存为SqlSession级别的缓存,也称为本地缓存;
3、以下4种情况将会导致该级缓存失效:
a、在不同SqlSession中查询数据;
b、相同SqlSession中查询数据,但查询条件不同
c、相同SqlSession中查询数据,但两次查询之间执行了增删改操作
d、相同SqlSession中查询数据,但第二次查询前,程序调用SqlSession对象clearCache()方法手动清除了一级缓存

二级缓存
    1、该级缓存默认开启,但如果使用二级缓存需要在每个XML映射文件中添加以配置该级缓存。二级缓存可以通过在全局配置文件配置setting标签来关闭该级缓存。
        cache标签属性:
            eviction:缓存回收策略:
                LRU – 最近最少使用的:移除最长时间不被使用的对象,默认值
                FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
                SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
                WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
            flushInterval:刷新间隔,单位毫秒,默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
            size:引用数目,正整数,代表缓存最多可以存储多少个对象,太大容易导致内存溢出
            readOnly:只读,默认为false。true:只读缓存;会给所有调用者返回缓存对象的相同实例,速度快;false:读写缓存;会返回缓存对象的拷贝(通过序列化),速度慢但安全。
    2、该级缓存为namespace级别的缓存
    3、工作机制:通过SqlSession查询数据,这些数据将会放到当前会话的一级缓存中;如果当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的SqlSession将从二级缓存中查找数据;
    4、select标签的useCache属性用于设置是否使用二级缓存;insert、update、delete或select标签均有flushCache属性,其中增删改默认true,即sql执行以后,会同时清空一级和二级缓存,查询默认false。
    5、为了提高扩展性,MyBatis定义了Cache缓存接口,可以通过实现该缓存接口自定义二级缓存,jar包下载:https://github.com/mybatis

一级缓存只能在同一次会话中产生作用。二级缓存在xml中设置cache标签,vo类实现序列化,同时必须关闭第一个会话,在第二次会话中才可以使用二级缓存。
(1)当为select语句时:
flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。
useCache默认为true,表示会将本条语句的结果进行二级缓存。
(2)当为insert、update、delete语句时:
flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。
useCache属性在该情况下没有。

在servlet中实现缓存技术,当是在一个会话中的时候,只有在第一次请求的时候是在数据库中请求数据,之后请求的都是一级缓存中的数据;

MyBatis数据缓存_第1张图片
1、

package com.lq.publisher.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 com.lq.publisher.IPublisherDao;
import com.lq.vo.PublishingHouse;

@WebServlet("/PublisherServlet")
public class PublisherServlet extends HttpServlet {

    SqlSession sqlSession;
    SqlSessionFactory sqlSessionFactory;
    private static final long serialVersionUID = 1L;

    @Override
    public void init() throws ServletException {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSession = sqlSessionFactory.openSession();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        IPublisherDao publisherDao = sqlSession.getMapper(IPublisherDao.class);
        List houseList = publisherDao.selectAll();
        System.out.println(houseList);
        request.setAttribute("houseList", houseList);
        request.getRequestDispatcher("./result.jsp").forward(request, response);
    }

    @Override
    public void destroy() {
        sqlSession.close();
    }
}

这里写图片描述
2、由于每一次请求都是一个新的SQLSession,第一次的会话没有关闭,不涉及到二级缓存,每次都是新的会话,所以每次都会在数据库中读取数据

package com.lq.publisher.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 com.lq.publisher.IPublisherDao;
import com.lq.vo.PublishingHouse;

@WebServlet("/PublisherServlet")
public class PublisherServlet extends HttpServlet {

    SqlSession sqlSession;
    SqlSessionFactory sqlSessionFactory;
    private static final long serialVersionUID = 1L;

    @Override
    public void init() throws ServletException {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        sqlSession = sqlSessionFactory.openSession();
        IPublisherDao publisherDao = sqlSession.getMapper(IPublisherDao.class);
        List houseList = publisherDao.selectAll();
        System.out.println(houseList);
        request.setAttribute("houseList", houseList);
        request.getRequestDispatcher("./result.jsp").forward(request, response);
    }

    @Override
    public void destroy() {
        sqlSession.close();
    }
}

MyBatis数据缓存_第2张图片

3、二级缓存:
在doGet请求中写SqlSession和close方法,第一次会话关闭,会将一级缓存中的数据缓存到二级缓存中。xml写标签,vo类中实现序列化。

package com.lq.publisher.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 com.lq.publisher.IPublisherDao;
import com.lq.vo.PublishingHouse;

@WebServlet("/PublisherServlet")
public class PublisherServlet extends HttpServlet {

    SqlSession sqlSession;
    SqlSessionFactory sqlSessionFactory;
    private static final long serialVersionUID = 1L;

    @Override
    public void init() throws ServletException {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            sqlSession = sqlSessionFactory.openSession();
            IPublisherDao publisherDao = sqlSession.getMapper(IPublisherDao.class);
            List houseList = publisherDao.selectAll();
            System.out.println(houseList);
            request.setAttribute("houseList", houseList);
            request.getRequestDispatcher("./result.jsp").forward(request, response);
        } finally{
            sqlSession.close();
        }
    }

    @Override
    public void destroy() {
    }
}

这里写图片描述

回望灯如旧,浅握双手

你可能感兴趣的:(mybatis)