zoukankan      html  css  js  c++  java
  • MyBatis的一, 二级缓存

    默认MyBatis开启了一级缓存, 在同一个sqlSession中, 如果命中同一个查询, MyBatis是不会真的查询的, 而只是拿结果对象糊弄你一下, 甚至如果这个对象被改了, 它也不管:

        @Test
        public void testCache() {
            SqlSession sqlSession = getSqlSession();
            SysUser user1 = null;
            try {
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                user1 = userMapper.selectById(1L);
                user1.setUserName("New Name");
                SysUser resultUser = userMapper.selectById(1L);
                System.out.println(user1);
                System.out.println(resultUser);
                Assert.assertEquals("New Name", resultUser.getUserName());
                Assert.assertEquals(user1, resultUser);
                // 这里的输出很惊人啊, user1改过名字, 理论上resultUser的userName不能跟user1一样啊.
                // 说明mybatis并未去真的查询, 而直接把结果拿来用了, 甚至对象都是直接拿来用了.可怕.
                // 这就是缓存的力量?
    
            } finally {
                sqlSession.close();
            }
    
            System.out.println("开启新的session");
    
            sqlSession = getSqlSession();
            try {
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                user1 = userMapper.selectById(1L);
                System.out.println("user1: " + user1);
                user1.setUserName("New Name");
                SysUser resultUser2 = userMapper.selectById(1L);
                System.out.println(user1);
                System.out.println(resultUser2);
                Assert.assertEquals("New Name", resultUser2.getUserName());
                Assert.assertEquals(user1, resultUser2);
                // 这里经过重新开启一个session之后, 又重新搜索了.
            } finally {
                sqlSession.close();
            }
        }

    这里对象名很乱, 不好意思.

    我们发现, 在session没关闭的情况下, 哪怕你把对象用setUserName方法改了, 再查询的时候, 它仍返回一个原来的结果对象, 变成了你查询的结果成了脏数据, 这是MyBatis的一级缓存的威力.

    OK, 开启二级缓存.

    首先拿SysRole对象做测试, 修改SysRole:

    public class SysRole implements Serializable {
    
        private static final long serialVersionUID = 3423434546568423L;
    
    ... ...

    SysRoleMapper的xml文件增加cache, 二级缓存只能针对namespace有效, 故这个namespace下的所有select都进入了缓存范围

    <mapper namespace="marc.mybatis.lesson1.mapper.SysRoleMapper">
        <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="false" />
    ... ...

    Mapper接口加个注解:

    @CacheNamespaceRef(SysRoleMapper.class)
    public interface SysRoleMapper {
    ... ...

    测试类如下, 注意, 这个测试类是拿SysRole而不是SysUser.

        @Test
        public void testLevel2Cache() {
            SqlSession sqlSession = getSqlSession();
            SysRole role1 = null;
            try {
                SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
                role1 = roleMapper.selectById(1L);
                role1.setRoleName("New Name");
                SysRole roleResult = roleMapper.selectById(1L);
                System.out.println(role1);
                System.out.println(roleResult);
                Assert.assertEquals("New Name", roleResult.getRoleName());
                Assert.assertEquals(role1, roleResult);
            } finally {
                sqlSession.close();
            }
    
            System.out.println("开启新的session");
    
            sqlSession = getSqlSession();
            try {
                SysRoleMapper roleMapper  = sqlSession.getMapper(SysRoleMapper.class);
                role1 = roleMapper.selectById(1L);
                System.out.println("user1: " + role1);
                //user1.setUserName("New Name");
                SysRole resultRole2 = roleMapper.selectById(1L);
                System.out.println(role1);
                System.out.println(resultRole2);
                Assert.assertEquals("New Name", resultRole2.getRoleName());
                Assert.assertNotEquals(role1, resultRole2);
            } finally {
                sqlSession.close();
            }
        }

    输出如下:

    DEBUG [main] - Cache Hit Ratio [marc.mybatis.lesson1.mapper.SysRoleMapper]: 0.0
    DEBUG [main] - ==>  Preparing: select id,role_name roleName,enabled,create_by createBy,create_time createTime from sys_role where id=? 
    DEBUG [main] - ==> Parameters: 1(Long)
    TRACE [main] - <==    Columns: id, roleName, enabled, createBy, createTime
    TRACE [main] - <==        Row: 1, 管理员, 1, 1, 2017-12-09 12:22:12.0
    DEBUG [main] - <==      Total: 1
    DEBUG [main] - Cache Hit Ratio [marc.mybatis.lesson1.mapper.SysRoleMapper]: 0.0
    SysRole [id=1, roleName=New Name, enabled=disabled, createBy=1, createTime=Sat Dec 09 12:22:12 CST 2017, user=null, privilegeList=null]
    SysRole [id=1, roleName=New Name, enabled=disabled, createBy=1, createTime=Sat Dec 09 12:22:12 CST 2017, user=null, privilegeList=null]
    开启新的session
    DEBUG [main] - Cache Hit Ratio [marc.mybatis.lesson1.mapper.SysRoleMapper]: 0.3333333333333333
    user1: SysRole [id=1, roleName=New Name, enabled=disabled, createBy=1, createTime=Sat Dec 09 12:22:12 CST 2017, user=null, privilegeList=null]
    DEBUG [main] - Cache Hit Ratio [marc.mybatis.lesson1.mapper.SysRoleMapper]: 0.5
    SysRole [id=1, roleName=New Name, enabled=disabled, createBy=1, createTime=Sat Dec 09 12:22:12 CST 2017, user=null, privilegeList=null]
    SysRole [id=1, roleName=New Name, enabled=disabled, createBy=1, createTime=Sat Dec 09 12:22:12 CST 2017, user=null, privilegeList=null]

    注意, 开启新的session之后, 仍然没有去真的查询, 而是击中了cache, 所以, 命中率一开始1/3, 后来变成了1/2, 而且注意看roleName, 全都被修改过. so, 注意使用缓存时产生的脏数据, 处理好这一点, 会让你的数据库更有效率, 数据吞吐量更大.

    想了想, 缓存的好处多半是用于处理搜索把, 比如你十月末在淘宝搜索羽绒服, 如果没有缓存, 数据库会疯掉......

  • 相关阅读:
    SQL 数据库备份
    压力测试工具WAS
    petshop4.0 详解之八(PetShop表示层设计
    类库生成的dll 添加 注释
    硬盘格式化后 数据全部找回
    petshop4.0 详解之七(PetShop表示层设计)
    JS 显示动态更新时间
    petshop4.0 详解之六(PetShop表示层设计)
    在linux环境下搭建嵌入式开发平台
    收录 Uboot 详解
  • 原文地址:https://www.cnblogs.com/Montauk/p/9797382.html
Copyright © 2011-2022 走看看