程序员

MyBatis缓存

2020-06-26  本文已影响0人  凡哥爱丽姐
正如大多数持久化框架一样,MyBatis提供了对一级缓存和二级缓存的支持。

1、一级缓存

    一级缓存作用范围是sqlSession域内,当sqlSession flush或者close之后,该sqlSession中所有的cache就会被清空,一般是自动开启的。
    下面我们以一个查询所有用户为例(添加驱动的jar包、创建MyBatis的核心配置文件mybatis-config.xml以及log4j我们就省略了,大家可以按照之前的教程自行配置)

    1.1、创建User实体类

package com.fan.entity;

public class User {
    private Integer id;
    private String name;
    private String sex;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

    1.2、创建UserDao接口类

package com.fan.dao;

import com.fan.entity.User;

import java.util.List;

public interface UserDao {
    //查询所有用户
    public List<User> findAllUser();

}

    1.3、添加mapper文件

<mapper namespace="com.fan.dao.UserDao">
    <select id="findAllUser" resultType="com.fan.entity.User">
        select * from users
    </select>
</mapper>

    1.4、添加测试类

import com.fan.dao.UserDao;
import com.fan.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

public class Test1 {
    public static void main(String[] args) {
        Reader resourceAsReader=null;
        SqlSession sqlSession=null;
        try {
            resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSession = new SqlSessionFactoryBuilder().build(resourceAsReader).openSession();

            UserDao mapper = sqlSession.getMapper(UserDao.class);
            List<User> allUser = mapper.findAllUser();
            for (User user:allUser) {
                System.out.println(user.getName());
            }

            System.out.println("---------------------------------------------");

            UserDao mapper1 = sqlSession.getMapper(UserDao.class);
            List<User> allUser1 = mapper1.findAllUser();
            for (User user1:allUser) {
                System.out.println(user1.getName());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
            if(resourceAsReader!=null){
                try {
                    resourceAsReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

    测试结果如下图所示(只调用了一次查询语句):

测试结果

    1.5、一级缓存失效情况

    1、查询不同的东西
    2、增删改操作,可能会改变原来的数据,所以必定会刷新缓存!
    3、查询不同的Mapper.xml
    4、手动清理缓存

2、二级缓存

    定义:

      二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。

      基于namespace级别缓存,一个名称空间,对应一个二级缓存。

      工作机制:

        1、一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中。

        2、如果当前会话关闭了,这个会话对应一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中。

        3、新的会话查询信息,就可以从二级缓存中获取内容。

        4、不同的mapper查出数据会放在自己对应的缓存中。

    2.1、在映射文件mapper设置缓存

<mapper namespace="接口路径">  
        <cache eviction="FIFO"
               flushInterval="60000"
               size="512"
               readOnly="true">
        </cache>
</mapper>  
说明:

     eviction: 二级缓存中,缓存的对象从缓存中移除的策略(上面FIFO的回收策略为先进先出)
    flushInterval: 刷新缓存的事件间隔
    size: 缓存对象的个数
    readOnly: 是否是只读的

    2.2、创建User实体类

package com.fan.entity;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String name;
    private String sex;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

    2.3、创建UserDao接口类

package com.fan.dao;

import com.fan.entity.User;

import java.util.List;

public interface UserDao {
    //查询所有用户
    public List<User> findAllUser();
}

    2.4、mapper文件中加入缓存cache的配置如下

<mapper namespace="com.fan.dao.UserDao">
    <cache eviction="FIFO"
               flushInterval="60000"
               size="512"
               readOnly="true">
    </cache>

    <select id="findAllUser" resultType="com.fan.entity.User">
        select * from users
    </select>
</mapper>

    2.5、测试类

import com.fan.dao.UserDao;
import com.fan.entity.User;
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 java.io.IOException;
import java.io.Reader;
import java.util.List;

public class Test1 {
    public static void main(String[] args) throws IOException {

            Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsReader);

            SqlSession sqlSession1 = factory.openSession();
            UserDao mapper = sqlSession1.getMapper(UserDao.class);
            List<User> allUser = mapper.findAllUser();
            for (User user:allUser) {
                System.out.println(user.getName());
            }
            sqlSession1.close();
            System.out.println("---------------------------------------------");

            SqlSession sqlSession2 = factory.openSession();
            UserDao mapper1 = sqlSession2.getMapper(UserDao.class);
            List<User> allUser1 = mapper1.findAllUser();
            for (User user1:allUser1) {
                System.out.println(user1.getName());
                sqlSession2.close();
            }
    }
}

    测试结果如下:

测试结果

    3、小结

      3.1、只要开启二级缓存,在同一个Mapper下就有效
      3.2、所有的数据都会先放在一级缓存中
      3.3、只有当会话提交,或者关闭的时候,才会提交到二级缓存中
上一篇下一篇

猜你喜欢

热点阅读