Mybatis缓存

本文介绍了Mybatis的缓存特性,包括一级缓存和二级缓存。一级缓存是SqlSession级别的,同一会话内的查询结果会被缓存,但增删改操作会导致缓存失效。二级缓存为SqlSessionFactory级别,需要手动开启并满足特定条件,如实体类实现序列化接口。查询顺序是先查二级缓存,再查一级缓存,最后才查询数据库。

Mybatis缓存**

  • mybatis包含了一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存。缓存可以极大的提高查询的效率

  • mybatis系统当中默认定义了两级缓存:一级缓存和二级缓存

    • 默认情况之下,只有一级缓存开启(sqlSession级别的缓存)
    • 二级缓存需要手动开启配置,需要局域namespace级别的缓存。
1.一级缓存

一级缓存也叫本地缓存

    • 与数据库同一次会话期间查询到的数据会放入的本地缓存当中。
    • 如果以后需要获取相同的数据直接去缓存当中拿,没必要再去查询数据库

缓存失效的情况

  • sqlSession不同
  • sqlSession相同,查询条件不同
  • sqlSession相同,两次查询之间执行了增删改操作!
  • sqlSession相同,手动清除一级缓存
二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactroy创建SqlSession查询结果会被缓存;此后若再次执行相同的查询语句,结果会从一个缓存中获取。

(1).二级缓存开启的条件

①:在核心配置文件中,设置全局属性caheEnable=“true”。

②:在映射件中置

③:查询数据所转换的实体类类型必须实现序列化接口

④:二级缓存必须在SqlSession关闭或提交之后有效

(2).二级缓存失效的情况

两次查询之间行了任意的增删改,会使得一级二级缓存同时失效

(3).开启二级缓存

①.在SqlMapConfig.xml配置文件中开启二级缓存

    <!‐‐ 开启二级缓存 ‐‐> 
    <settings>    
    <!--开启二级缓存-->    
    <setting name="cacheEnabled" value="true"/> 
    </settings>             

②. 在UserDao.xml配置文件声明使用二级缓存

   <!--使用二级缓存--> <cache/>              

③:查询数据所转换的实体类类型必须实现序列化接口

public class User implements Serializable {    
    private Integer id;    
    private String username;    
    private Date birthday;    
    private String sex;    
    private String address;    
    // get set方法 .....
}     

④:二级缓存必须在SqlSession关闭或提交之后有效

@Test public void findById() throws IOException {    
    // 1.加载SqlMapConfig配置文件    
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");    
    //2.创建sqlSessionFactory工厂    
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);    
    //3.sqlSessionFactory创建sqlSession    
    SqlSession sqlSession = factory.openSession();    
    SqlSession sqlSession2 = factory.openSession();     
    //4.通过Session创建UserDao接口代理对象    
    UserDao mapper = sqlSession.getMapper(UserDao.class);    
    User user1 = mapper.findById(1);    
    System.out.println(user1.toString());    
    // 将其一级缓存的数据放进二级缓存中,并清空一级缓存    
    sqlSession.close();     
    System.out.println("-----------------");    
    UserDao mapper2 = sqlSession2.getMapper(UserDao.class);    
    User user2 = mapper2.findById(1);    
    System.out.println(user2.toString());    
    // 将其一级缓存的数据放进二级缓存中,并清空一级缓存    
    sqlSession2.close();     
    System.out.println(user1 == user2);        
    resourceAsStream.close(); 
}       

(4).重要结论

打印发现2个对象的地址值不一样,但是确实只发送了一次SQL语句的查询,二级缓存中存储的是数据,不是对象。

三、Mybatis缓存查询顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序查询出来的数据,可以直接拿来使用
  • 如果二级缓存命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库
  • SqlSession关闭之后,一级缓存的数据会写入二级缓存
### 三级标题:MyBatis 缓存机制的工作原理 MyBatis 提供了两种级别的缓存机制:一级缓存和二级缓存,分别适用于不同的使用场景,并通过特定的数据结构实现查询结果的存储与复用。 一级缓存是 SqlSession 级别的缓存,默认情况下是开启的。每个 SqlSession 都会维护一个本地缓存(基于 HashMap 实现),用于存储该 SqlSession 中执行过的查询结果。在同一个 SqlSession 中,如果执行相同的查询语句,则 MyBatis 会直接从缓存中获取数据,而不会再次访问数据库[^3]。当执行插入、更新或删除操作时,MyBatis 会自动清空当前 SqlSession 的一级缓存,以确保数据的一致性[^1]。 二级缓存是 Mapper(namespace)级别的缓存,多个 SqlSession 可以共享同一个 Mapper 的二级缓存。这意味着跨 SqlSession 的查询可以复用缓存数据,前提是这些查询属于相同的 Mapper 命名空间。二级缓存需要显式配置,可以通过接口注解方式实现,例如使用 `@CacheNamespace` 注解来启用指定 Mapper 接口的二级缓存功能[^2]。 以下是一个使用注解方式配置 MyBatis 二级缓存的示例: ```java @CacheNamespace public interface UserMapper { User getUserById(int id); } ``` ### 三级标题:MyBatis 缓存的使用注意事项 尽管缓存机制可以显著提升数据库查询性能,但在实际应用中需要注意以下几点。 首先,一级缓存的作用范围仅限于当前 SqlSession,不同 SqlSession 之间的缓存数据互不影响。因此,在涉及多个 SqlSession 或事务隔离级别较高的场景下,不能依赖一级缓存保证数据一致性[^4]。 其次,二级缓存虽然支持跨 SqlSession 共享数据,但其默认实现并不具备线程安全特性。在并发访问频繁的环境中,建议引入第三方缓存组件(如 Ehcache 或 Redis)以提高稳定性和可扩展性。此外,二级缓存的生命周期独立于 SqlSession,即使关闭或清除 SqlSession,缓存数据依然存在,因此必须谨慎管理缓存更新策略,避免出现脏读问题[^1]。 最后,由于缓存机制的存在,某些情况下可能会导致查询结果与数据库中的最新数据不一致。为了解决这一问题,可以在执行写操作后手动刷新缓存,或者通过配置合理的缓存失效时间来控制数据同步的粒度。同时,应避免对频繁更新的数据使用缓存,以免因频繁清空缓存而抵消性能优化效果[^3]。 ### 三级标题:相关代码示例 以下是一个展示 MyBatis 一级缓存行为的简单示例。在这个例子中,两次调用相同的查询方法将只触发一次数据库访问: ```java public class UserService { @Autowired private SqlSession sqlSession; public void testCache() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 第一次查询,结果从数据库中获取 User user1 = mapper.getUserById(1); // 第二次查询相同的记录,结果从一级缓存中获取,不再访问数据库 User user2 = mapper.getUserById(1); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值