手记

追加Mybatis的一级,二级缓存

一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。作用域为namespance是指对该namespance对应的配置文件中所有的select操作结果都缓存,这样不同线程之间就可以共用二级缓存。

启动二级缓存:在mapper配置文件中:<cache readOnly="true"/>。
3.一级缓存测试实例

/** 
     * 测试mybatis一级缓存,即session作用域缓存 (  CommandFile 是一个实体类)
     */  
    @Test  
    public void testSelect_sessionCache() {  
        String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";  
        SqlSession session = SqlSessionUtil.openSession();  
        CommandFile commandFile1 = session.selectOne(statement,4l);  
        CommandFile commandFile2 = session.selectOne(statement,4l);  
        //commandFile2是从一级缓存中返回的缓存对象,与commandFile1同一个对象实例。  
        Assert.assertEquals(commandFile1, commandFile2);  
        //session关闭时清空缓存  
        session.close();  
        //显示清空缓存  
//            session.clearCache();  
        session = SqlSessionUtil.openSession();  
        CommandFile commandFile3 = session.selectOne(statement,4l);  
        //查询时commandFile3,一级缓存已经被清空,commandFile3与commandFile1不是同一个对象实例  
        Assert.assertNotEquals(commandFile1, commandFile3);  
        CommandFile commandFile4 = session.selectOne(statement,5l);  
        //一级缓存中不存在id为5的缓存对象,所以commandFile4是从数据库中查找出的实例。  
        Assert.assertNotEquals(commandFile3, commandFile4);  
    }  

/** 
     * 测试mybatis一级缓存,即session作用域缓存 (将session.close()换为执行一个update语句,也会导致一级缓存清空。)
     */  
    @Test  
    public void testSelect_sessionCache2() {  
        String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";  
        SqlSession session = SqlSessionUtil.openSession();  
        CommandFile commandFile1 = session.selectOne(statement,4l);  
        //执行更新后清空缓存  
        commandFile1.setName("bigfile-uploader2");  
        session.update("com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.update",commandFile1);  
        CommandFile commandFile2 = session.selectOne(statement,4l);  
        //查询commandFile2时,一级缓存已经被清空,commandFile2与commandFile1不是同一个对象实例  
        Assert.assertNotEquals(commandFile1, commandFile2);  
    }  

/** 
     * 测试mybatis二级缓存:nameSpace作用域 
     * <cache readOnly="false"/> 
     */  
    @Test  
    public void testSelect_nameSpaceCache() {  
        String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";  
        SqlSession sqlSession1 = SqlSessionUtil.openSession();  
        SqlSession sqlSession2 = SqlSessionUtil.openSession();  

        //使用二级缓存时,CommandFile类必须实现一个Serializable接口  
        CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);  
        //sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存  
        sqlSession1.commit();  
        CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);  
        /** 
         * <cache readOnly="false"/>时,返回缓存对象的拷贝,所以返回的commandFile2 != commandFile1 
         * 这样一个调用者有修改这个自己的缓存对象时,其他调用者不受影响。 
         */  
       Assert.assertNotEquals(commandFile1, commandFile2);  
    }  

/** 
     * 测试mybatis二级缓存:nameSpace作用域 
     * <cache readOnly="true"/> 
     */  
    @Test  
    public void testSelect_nameSpaceCache2() {  
        String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";  
        SqlSession sqlSession1 = SqlSessionUtil.openSession();  
        SqlSession sqlSession2 = SqlSessionUtil.openSession();  

        //使用二级缓存时,CommandFile类必须实现一个Serializable接口  
        CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);  
        //sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存  
        sqlSession1.commit();  
        CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);  
        /** 
         * <cache readOnly="true"/>时,对所有调用者返回同一个缓存对象,即同一个实例。 
         * 这样一个调用者有修改这个缓存对象时,其他调用者可能就会出现数据不一致的问题。 
         */  
        Assert.assertEquals(commandFile1, commandFile2);  
    }  

/** 
     * 测试mybatis二级缓存:nameSpace作用域 
     * 执行update操作,会清空二级缓存 
     */  
    @Test  
    public void testSelect_nameSpaceCache3() {  
        String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";  
        SqlSession sqlSession1 = SqlSessionUtil.openSession();  
        SqlSession sqlSession2 = SqlSessionUtil.openSession();  
        SqlSession sqlSession3 = SqlSessionUtil.openSession();  

        //使用二级缓存时,CommandFile类必须实现一个Serializable接口  
        CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);  
        //sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存  
        sqlSession1.commit();  
        CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);  
        /** 
         * <cache readOnly="true"/>时,对所有调用者返回同一个缓存对象,即同一个实例。 
         * 这样一个调用者有修改这个缓存对象时,其他调用者可能就会出现数据不一致的问题。 
         */  
        Assert.assertEquals(commandFile1, commandFile2);  
        commandFile2.setName("bigfile-uploader");  
        sqlSession2.update("com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.update", commandFile2);  
//      执行commit()表示执行update操作,会清空二级缓存中的数据  
        sqlSession2.commit();  
        CommandFile commandFile3 = sqlSession3.selectOne(statement, 4l);  
        //查询时,二级缓存中没有缓存数据了  
        Assert.assertNotEquals(commandFile2, commandFile3);  
    }  
2人推荐
随时随地看视频
慕课网APP