您的当前位置:首页正文

MyBatis教程--缓存(六)

2024-11-09 来源:个人技术集锦

1 介绍

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
  • MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,他是基于 namespace级别的缓存。
    • 为了提高扩展性, MyBatisCache定义了缓存接口我们可以通过实现 Cache接口来自定义二级缓存

2 一级缓存

  • 一级缓存也叫本地缓存:
    • 与数据库同一次会话期间查询到的数据会放在本地缓存中
    • 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
    • 范围是连接到关闭连接这个范围
@Test
public void testQueryUserById(){
     try (SqlSession sqlSession = MybatisUtil.getSqlSession()) {
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         User user = mapper.queryUserById(1);
         System.out.println(user.toString());
         System.out.println("---------------");
         User user2 = mapper.queryUserById(1);
         System.out.println(user2.toString());
         System.out.println(user == user2);
     }
 }

运行结果

==>  Preparing: select id, password, username from t_user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, password, username
<==        Row: 1, 123456, jinjing
<==      Total: 1
User{id=1, userName='jingMyTypeHandler', password='123456MyTypeHandler'}
---------------
User{id=1, userName='jingMyTypeHandler', password='123456MyTypeHandler'}
true

从运行结果可以看出我们查询了两次id = 1的用户,但是sql只执行了一次,同时我们发现最后user 与user2通过==比较结果是true,说明第二次查询结果就是从内存里取出同user对象对user2进行赋值给的

缓存失效的情况:

3 二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于 namespace级别的缓存,一个名称空间,对应一个二级缓存
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的
    • 数据被保存到二级缓存中;
    • 新的会话查询信息,就可以从二级缓存中获取内容;
    • 不 mapper同的查出的数据会放在自己对应的缓存(map)中

mybatis-config.xml
在mybatis核心配置文件中显示的打开二级缓存

<settings>
  <setting name="cacheEnabled" value="true"/>
</settings>

UserMapper.xml
在用缓存的mapper里面配置缓存信息

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
<!--单独配置某个sql不走缓存useCache="false",是否刷新缓存flushCache="false"-->
<select id="queryAllUser" resultType="User" flushCache="false" useCache="false">
   select * from t_user
</select>
    @Test
    public void testQueryUserById(){
        User user;
        User user2;
        try (SqlSession sqlSession = MybatisUtil.getSqlSession()) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            user = mapper.queryUserById(1);
            System.out.println(user.toString());
        }
        System.out.println("---------------");
        try (SqlSession sqlSession = MybatisUtil.getSqlSession()) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            user2 = mapper.queryUserById(1);
            System.out.println(user2.toString());
        }
        System.out.println(user == user2);
    }
==>  Preparing: select id, password, username from t_user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, password, username
<==        Row: 1, 123456, jinjing
<==      Total: 1
User{id=1, userName='jingMyTypeHandler', password='123456MyTypeHandler'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7c6908d7]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7c6908d7]
Returned connection 2087258327 to pool.
---------------
Cache Hit Ratio [com.jing.dao.UserMapper]: 0.5
User{id=1, userName='jingMyTypeHandler', password='123456MyTypeHandler'}
true

Process finished with exit code 0

从运行结果可以看出我们查询了两次id = 1的用户,但是sql只执行了一次,同时我们发现最后user 与user2通过==比较结果是true,说明第二次查询结果就是从内存里取出同user对象对user2进行赋值给的

3.1 cache属性介绍

<cache
  type="com.domain.something.MyCustomCache"
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

eviction 对应的是清楚策略, 默认为 LRU

  1. LRU – 最近最少使用:移除最长时间不被使用的对象。
  2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  3. SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  4. WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。
size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。
type 自定义缓存,其属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口,且提供一个接受 String 参数作为 id 的构造器

显示全文