Mybatis源码学习二一级缓存

一级缓存流程

Mybatis源码学习二一级缓存

一级缓存有效的因素

Mybatis源码学习二一级缓存

一级缓存有效测试

public class User {
    private Integer id;
    private String name;

    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 interface UserMapper {

    @Select("select name from user where id = #{id}")
    String selectById(@Param("id") int id);

    @Update("update user set name=#{arg1} where id=#{arg0}")
    void updateById(int id,String name);

    @Select("select * from user where id = #{id}")
    User selectUserById(@Param("id") int id);

    @Select("select * from user where id = #{id}")
    User selectUserById2(@Param("id") int id);
}
public class FirstCacheTest {

    private SqlSessionFactory sqlSessionFactory;
    private SqlSession sqlSession;

    @Before
    public void init() throws IOException {
        //获取构造器
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //解析XML 并构造会话工厂
        sqlSessionFactory = builder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        sqlSession = sqlSessionFactory.openSession();
    }

    /**
     * SQL和参数必须相同
     */
    @Test
    public void test1(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user1 = userMapper.selectUserById(1);
        User user2 = userMapper.selectUserById(1);
        System.out.println(user1==user2); //true 表示走一级缓存
    }
    /**
     * 必须是相同的statementID
     */
    @Test
    public void test2(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //statementID: dao.UserMapper.selectUserById
        User user1 = userMapper.selectUserById(1);
        //statementID: dao.UserMapper.selectUserById2
        User user2 = userMapper.selectUserById2(1);
        System.out.println(user1==user2); //false
    }

    /**
     * sqlSession必须一样,一级缓存也叫会话级缓存
     */
    @Test
    public void test3(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user1 = userMapper.selectUserById(1);
        User user2 = sqlSessionFactory.openSession().getMapper(UserMapper.class).selectUserById(1);
        System.out.println(user1==user2); //false
    }

    /**
     * RowBounds 返回行范围必须相同
     */
    @Test
    public void test4(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user1 = userMapper.selectUserById(1);
        //分页
        RowBounds rowBounds = new RowBounds(0, 1);
        List list = sqlSession.selectList("dao.UserMapper.selectUserById",1,rowBounds);
        System.out.println(user1==list.get(0)); //false
    }

    /**
     * 未手动清空缓存
     * 未执行update (数据一致性)
     * 未提交或回滚
     */
    @Test
    public void test5(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user1 = userMapper.selectUserById(1);
        //sqlSession.clearCache();
        //userMapper.updateById(2,"eee");
        sqlSession.commit();
        User user2 = userMapper.selectUserById(1);
        System.out.println(user1==user2); //false
    }
}

 源码分析一级缓存失效原因

运行时参数相关

Mybatis源码学习二一级缓存

首先从localCache 中获取数据,先判断key 的组成。

Mybatis源码学习二一级缓存

 key是在Executor里,而Executor在SqlSession里,所以必须是在同一个会话中。5:mysql是设置的环境,一般操作肯定是在同一个环境中,可以不考虑。

操作与配置相关

Mybatis源码学习二一级缓存

queryStack是用于嵌套查询的,等于0表示没有子查询。子查询依赖一级缓存,不能删除缓存。

Mybatis源码学习二一级缓存

Mybatis源码学习二一级缓存

Mybatis源码学习二一级缓存

Mybatis源码学习二一级缓存

Mybatis源码学习二一级缓存

清除缓存的操作完全符合之前的描述。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容