关于mybatis:mybatis的缓存机制

前言

最近在应用mybatis的时候发现了一个问题:当我进行更新操作时,通过id查问条件查出一个User对象,并批改user的姓名,在进行update函数前,通过切面去记录他的变更信息到变更记录表中。

public User update(User user) {
    User oldUser = new User();
    oldUser.setId(user.getId());
    oldUser = this.daoSupport.selectOne(oldUser);
    oldUser.setName(user.getName());
    return this.daoSupport.update(oldUser);
}

在切面中,通过这个对象的主键去数据库查问到变更前的的值,和变更后的值做比照,不雷同的属性即为理论变更的属性。然而发现,在切面里通过主键查问进去的对象的各个属性值为变更后的值,这明明是在update之前的切面,变更内容并没有保留到数据库中,为何查问进去的值为变更后的值呢?
为了排除切面的影响,我在查问并批改user的姓名后,在update语句前,再次查问user。

public User update(User user) {
    User oldUser = new User();
    oldUser.setId(user.getId());
    oldUser = this.daoSupport.selectOne(oldUser);
    oldUser.setName(user.getName());
    User oldUser1 = new User();
    oldUser1.setId(user.getId());
    oldUser1 = this.daoSupport.selectOne(oldUser1);
    return this.daoSupport.update(oldUser);
}

此时,也的确是变更后的值,并且通过断点发现两个user为同一个对象,也就是说对象指针地址一样,那必定是变更后的值。猜想是存在着一种缓存机制,使得第二次查问应用了第一次查问的后果,然而这个后果是一个对象指针。

MyBatis缓存

再网上查问得悉,mybatis的确有一种缓存机制,并且分为一级缓存和二级缓存。

在理解一级缓存前,先理解一下mybatis的SqlSession。
在mybatis的根底写法中,咱们都是先获取SqlSession,而后通过SqlSession再去进行我的定义的mapper操作,当然DaoSupport定义了一些根本mapper操作且不须要手动定义SqlSession,然而实质上也是通过SqlSession对数据库进行操作。

通过浏览源码得悉,mybatis的一级缓存,就是在一个SqlSession的生命周期内,在进行一次查问时,将查问后果和查问条件存起来,在进行下一次查问时,先去匹配查问条件,若查问条件雷同,便不在去查询数据库,而是将上一次的查问后果返回,当然这里返回的是对象指针。那么就不难理解呈现的问题了。

解决

解决很好解决。
一种办法是全局敞开缓存,设置 mybatis.configuration.local-cache-scope=statement

一种办法时是第二次查问前清空缓存。

SqlSession sqlSession = SqlSessionUtils.getSqlSession(sqlSessionFactory);
sqlSession.clearCache();

其中sqlSessionFactory时通过依赖注入的。

源码浏览

对于具体机制浏览,举荐两篇文章
【不懂就问】MyBatis的一级缓存居然还会引来麻烦?
聊聊MyBatis缓存机制
(另外举荐一下美团技术团队的文章,写的都很好,大家能够浏览一下,下面的第二篇文章和上次的雪花算法都来自于那里。美团技术团队)

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据