MyBatis缓存

作者: 凡哥爱丽姐 | 来源:发表于2020-06-26 10:10 被阅读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、只有当会话提交,或者关闭的时候,才会提交到二级缓存中

    相关文章

      网友评论

        本文标题:MyBatis缓存

        本文链接:https://www.haomeiwen.com/subject/ewegohtx.html