• 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, 注意使用缓存时产生的脏数据, 处理好这一点, 会让你的数据库更有效率, 数据吞吐量更大.

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

  • 相关阅读:
    Git 基础
    SharePoint 2013 对象模型操作"网站设置"菜单
    SharePoint 2013 隐藏部分Ribbon菜单
    SharePoint 2013 Designer系列之数据视图筛选
    SharePoint 2013 Designer系列之数据视图
    SharePoint 2013 Designer系列之自定义列表表单
    SharePoint 2013 设置自定义布局页
    SharePoint 2013 "通知我"功能简介
    SharePoint 2013 创建web应用程序报错"This page can’t be displayed"
    SharePoint 禁用本地回环的两个方法
  • 原文地址:https://www.cnblogs.com/Montauk/p/9797382.html
Copyright © 2020-2023  润新知