详解mybatis的一二级缓存以及缓存失效原因

数据库的大部分场景下是从磁盘读取,如果数据从内存进行读取,速度较比磁盘要快得多。但因为内存的容量有限,所以一般只会把使用和查询较多的数据缓存起来,以便快速反应,其他使用率不太多的继续存放在磁盘。

mybatis分为一级缓存和二级缓存

1.一级缓存

一级缓存存放在SqlSqeeion上,默认开启

1.1pojo

@Data
public class Role{
	private Long id;
	private String roleName;
	private String note;
}

1.2Mapper

public interface RoleMapper {
   Role getRole (long id);
}

1.3xml文件

<mapper namespace="mybatis04.mapper.RoleMapper">
   
    <select id="getRole" resultType="role">
        select id,role_name as roleName,note from t_role where id=#{id}
    </select>
</mapper>

1.4测试一级缓存


public class Mybatis04Test {
    public static void main(String[] args) {
    getRole();
    }

    public static void getRole(){
        SqlSession sqlSession=null;
      
        try {
            Logger logger = Logger.getLogger(Mybatis04Test.class);
            sqlSession = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role=roleMapper.getRole(1l);
            logger.debug("获取pojo对象"+role);
            RoleMapper roleMapper1=sqlSession.getMapper(RoleMapper.class);
            Role role1=roleMapper1.getRole(1l);
            logger.debug("同SqlSession获取pojo对象"+role1);

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}

执行查看日志

 发现虽然出现两个结果,但是sql却只出现了一条,mybatis的一级缓存存在于SqlSession中,如果SqlSession第一次通过sql和参数获取对象后就会将其缓存,第二次查询如果sql和参数没有变化就会从缓存中获取数据,不会再次连接数据库。

1.5使用不同SqlSession测试

public class Mybatis04Test {
    public static void main(String[] args) {
    getRole();
    }

    public static void getRole(){
        SqlSession sqlSession=null;
        SqlSession sqlSession1=null;
        try {
            Logger logger = Logger.getLogger(Mybatis04Test.class);
            sqlSession = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role=roleMapper.getRole(1l);
            logger.debug("获取pojo对象"+role);
            RoleMapper roleMapper1=sqlSession.getMapper(RoleMapper.class);
            Role role1=roleMapper1.getRole(1l);
            logger.debug("同SqlSession获取pojo对象"+role1);
            sqlSession.close();
            //不同SqlSession获取pojo
            sqlSession1=SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper2=sqlSession1.getMapper(RoleMapper.class);
            Role role2=roleMapper2.getRole(1l);
            logger.debug("不同SqlSession获取pojo"+role2);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}

 查看日志

 发现日志中出现两条sql,此测试可以确定一级缓存是存在在SqlSession中的,

2.二级缓存

二级缓存存放在SqlSessionFactory需要通过配置开启,并且POJO对象需要实现序列化接口

2.1配置二级缓存

 配置二级缓存很简单,在xml文件中加入<cache/>元素即可

POJO对象实现序列化接口

2.2测试二级缓存

public class Mybatis04Test {
    public static void main(String[] args) {
    getRole();
    }

    public static void getRole(){
        SqlSession sqlSession=null;
        SqlSession sqlSession1=null;
        try {
            Logger logger = Logger.getLogger(Mybatis04Test.class);
            sqlSession = SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            Role role=roleMapper.getRole(1l);
            logger.debug("获取pojo对象"+role);
            RoleMapper roleMapper1=sqlSession.getMapper(RoleMapper.class);
            Role role1=roleMapper1.getRole(1l);
            logger.debug("同SqlSession获取pojo对象"+role1);
            sqlSession.commit();
            //不同SqlSession获取pojo
            sqlSession1=SqlSessionFactoryUtils.openSqlSession();
            RoleMapper roleMapper2=sqlSession1.getMapper(RoleMapper.class);
            Role role2=roleMapper2.getRole(1l);
            sqlSession1.commit();
            logger.debug("不同SqlSession获取pojo"+role2);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}

测试二级缓存需要commit提交,如果不提交是不会保存到二级缓存的

2.3查看日志

日志中三个结果只有一条sql,证明是从SqlSessionFactory获取缓存

缓存失效

对数据进行INSERT,UPDATE,DELETE,或者清除缓存都会造成缓存失效 


版权声明:本文为m0_56058975原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。