说一下 mybatis 的一级缓存和二级缓存?

一级缓存失效包括SqlSession关闭、执行更新操作、手动清空缓存或查询条件变化;二级缓存需在全局配置中启用cacheEnabled,在Mapper中添加标签,并确保POJO实现Serializable接口。

MyBatis的一级缓存是Session级别的,而二级缓存是namespace级别的。一级缓存默认开启,无需配置;二级缓存需要手动开启和配置。

MyBatis的缓存机制,是为了提高查询效率,减少数据库压力。一级缓存的存在,让同一个Session内,相同的查询语句可以直接从缓存中获取结果,避免重复查询数据库。而二级缓存,则允许跨Session共享缓存数据,进一步提升性能。

一级缓存失效的几种情况?

一级缓存是和SqlSession绑定的,它的生命周期与SqlSession一致。所以,SqlSession关闭时,一级缓存也就失效了。但除了SqlSession的生命周期,还有一些操作会导致一级缓存失效:

  • 执行任何更新操作(update、insert、delete):因为更新操作会修改数据库中的数据,为了保证数据的一致性,MyBatis会清空一级缓存。
  • 手动清空缓存:可以通过调用sqlSession.clearCache()方法手动清空一级缓存。
  • 不同的SqlSession:即使查询条件完全相同,不同的SqlSession也会创建自己的一级缓存,彼此之间互不影响。
  • 相同的SqlSession,但查询条件不同:虽然在同一个SqlSession中,但如果两次查询的查询条件不同,MyBatis会执行两次查询,并分别将结果缓存起来。

总之,一级缓存失效的核心原则是:任何可能导致数据不一致的操作,都会导致一级缓存失效。

二级缓存如何配置才能生效?

要让MyBatis的二级缓存生效,需要在多个地方进行配置。

  1. 开启二级缓存:在MyBatis的全局配置文件(通常是mybatis-config.xml)中,需要开启二级缓存。

    
      
        
      
      ...
    
  2. 在Mapper文件中配置cache元素:在需要使用二级缓存的Mapper文件中,添加元素。可以自定义缓存的配置,例如缓存的刷新间隔、缓存的大小等。

    
      
      ...
    
    • eviction:缓存回收策略,常见的有LRU(最近最少使用)、FIFO(先进先出)等。
    • flushInterval:缓存刷新间隔,单位是毫秒。如果设置为0,则表示不刷新。
    • size:缓存的大小,表示最多可以存储多少个对象。
    • readOnly:是否只读。如果设置为true,则表示缓存中的对象是只读的,不能被修改。
  3. POJO类需要实现Serializable接口:因为二级缓存可能会将对象序列化到磁盘上,所以需要确保POJO类实现了java.io.Serializable

    口。

  4. select语句需要配置useCache="true":默认情况下,select语句会使用二级缓存。如果不需要使用二级缓存,可以将useCache属性设置为false

  5. 更新操作需要配置flushCache="true":默认情况下,update、insert、delete语句会清空二级缓存。如果不需要清空二级缓存,可以将flushCache属性设置为false。但是,通常不建议这样做,因为可能会导致数据不一致。

配置完成后,MyBatis就会自动使用二级缓存来提高查询效率。

如何选择使用一级缓存还是二级缓存?

选择使用哪种缓存,或者同时使用两种缓存,取决于具体的应用场景和需求。

  • 一级缓存适用场景:适用于单个会话内需要频繁查询相同数据的场景。由于一级缓存的生命周期与SqlSession一致,因此在同一个会话内,可以避免重复查询数据库。
  • 二级缓存适用场景:适用于多个会话之间需要共享缓存数据的场景。例如,对于一些不经常变动的配置信息、字典数据等,可以使用二级缓存来提高查询效率。

一般来说,建议同时使用一级缓存和二级缓存。一级缓存可以提高单个会话内的查询效率,而二级缓存可以提高多个会话之间的查询效率。但是,需要注意的是,二级缓存可能会导致数据一致性问题,因此需要谨慎使用。

例如,一个电商网站的商品信息,可以考虑使用二级缓存。因为商品信息不经常变动,而且多个用户可能会查询相同的商品信息。但是,对于库存信息,则不适合使用二级缓存,因为库存信息是经常变动的,使用二级缓存可能会导致超卖等问题。

总而言之,选择使用哪种缓存,需要根据具体的应用场景和需求进行权衡。没有绝对的正确答案,只有最适合的解决方案。