Mybatis的一级缓存和二级缓存的理解以及用法

简介: 先了解一下缓存的概念:原始意义是指访问速度比一般随机存取存储器快的一种RAM,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。对于我们编程来说,所谓的缓存,就是将程序或系统经常要调用的对象(临时数据)存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统的开销,提高效率。

程序中为什么使用缓存?

 先了解一下缓存的概念:原始意义是指访问速度比一般随机存取存储器快的一种RAM,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。对于我们编程来说,所谓的缓存,就是将程序或系统经常要调用的对象(临时数据)存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统的开销,提高效率。

 对缓存有了一定的了解以后就知道了使用缓存是为了减少和数据库的交互次数,提高执行效率。那么下一个问题来了,什么样的数据能使用缓存,什么样的数据不能使用呢?

 这是我们使用缓存必须要明确的事情,实际上适用于缓存的数据指:经常查询并且不经常改变的,并且数据的正确与否对最终结果影响不大的,不适用于缓存的数据:经常改变的数据,数据的正确与否对最终结果影响很大的。

 Mybatis中的一级缓存和二级缓存到底缓存了什么,缓存了以后又有什么效果,缓存的数据什么时候会被清空?

 一级缓存:它指的是Mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入到SqlSession中为我们提供的一块区域中,该区域的结构是一个Map,当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用,当SqlSession对象消失时,mybatis的一级缓存也就消失了,同时一级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除、commit(),close等方法时,就会清空一级缓存。

 二级缓存:他指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存,但是其中缓存的是数据而不是对象,所以从二级缓存再次查询出的结果对象与第一次存入的对象是不一样的。

 通过简单的例子来加深理解一级缓存和二级缓存。

一级缓存

1.用户类

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

2.Dao层

public interface UserDao {
    /**
     * 查询所有的用户
     *
     * @return
     */
    List<User> findAll();
    /**
     * 根据Id查询用户
     *
     * @return
     */
    User findById(Integer id);
    /**
     * 更新用户
     * @param user
     */
    void updateUser(User user);
}

3.UserDao.xml映射文件

<mapper namespace="com.example.dao.UserDao">
    <select id="findAll" resultType="com.example.domain.User">
        SELECT * FROM USER;
    </select>
    <select id="findById" resultType="com.example.domain.User" parameterType="INT">
        SELECT * FROM  USER  WHERE ID = #{ID}
    </select>
    <update id="updateUser" parameterType="com.example.domain.User">
        update USER
        <set>
            <if test="username != null">username=#{username},</if>
            <if test="password != null">birthday=#{birthday},</if>
            <if test="sex != null">sex=#{sex},</if>
            <if test="address != null">address=#{address},</if>
        </set>
        where id=#{id}
    </update>
</mapper>

在以上三步中这是mybatis的单表操作,下面通过根据用户ID查询用户的操作来观察一级缓存生效与否的区别  

4.测试

(1) 命中一级缓存的情况

测试代码:

@Test
public void findByIdTest(){
    session = factory.openSession();
    userDao = session.getMapper(UserDao.class);
    //第一次获取该用户
    User user1 = userDao.findById(45);
    System.out.println(user1);
    第二次获取该用户
    User user2 = userDao.findById(45);
    System.out.println(user2);
    System.out.println(user1 == user2);
    session.close();
}

测试结果:


(2)对SqlSession进行清除缓存的操作,即清楚一级缓存,然后再次进行测试。

@Test
public void findByIdTest(){
    session = factory.openSession();
    userDao = session.getMapper(UserDao.class);
    User user1 = userDao.findById(45);
    System.out.println(user1);
    //session.commit(); 调用SqlSession的commit方法清空缓存
    user1.setUsername("更新用户");
    user1.setAddress("更新地址");
    userDao.updateUser(user1);//通过更新SqlSession清空缓存
    User user2 = userDao.findById(45);
    System.out.println(user2);
    System.out.println(user1 == user2);
    session.close();
}

清空缓存的操作很多,可以都试试。测试结果:

二级缓存  

 再看一下Mybatis二级缓存是如何使用的,第一步让Mybatis框架支持二级缓存(在Mybatis的主配置文件中配置),第二步让当前的映射文件支持二级缓存(在Dao.xml映射文件中配置),第三步让当前的方法支持二级缓存(在标签中配置)。根据这个步骤将上面的查询用户的接口通过配置改造为可以支持二级缓存的方法。

1.配置Mybatis框架支持二级缓存

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

2.配置UserDao.xml支持二级缓存

<cache/>

3.配置查询的方法支持二级缓存

<select id="findById" resultType="com.example.domain.User" parameterType="INT" useCache="true">
    SELECT * FROM  USER  WHERE ID = #{ID}
</select>

4.测试

@Test
public void findByIdTest(){
    //第一次查询 并更新二级缓存
    SqlSession session1 = factory.openSession();
    UserDao userDao1 = session1.getMapper(UserDao.class);
    User user1 = userDao1.findById(45);
    System.out.println(user1);
    session1.commit(); //commit()方法提交二级缓存 同时清空一级缓存
    session1.close();//
  //user1.setUsername("更新用户");
  //user1.setAddress("更新地址");
  //userDao.updateUser(user1);//通过更新SqlSession清空缓存
    //第二次查找命中二级缓存
    SqlSession session2 = factory.openSession();
    UserDao userDao2 = session2.getMapper(UserDao.class);
    User user2 = userDao2.findById(45);
    session2.commit(); //commit()方法提交二级缓存 同时清空一级缓存
    session2.close();//
    System.out.println(user2);
    System.out.println(user1 == user2);
}

测试结果:

总结:mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。二级缓存是SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二级缓存>一级缓存>数据库。


目录
相关文章
|
存储 缓存 芯片
让星星⭐月亮告诉你,当我们在说CPU一级缓存二级缓存三级缓存的时候,我们到底在说什么?
本文介绍了CPU缓存的基本概念和作用,以及不同级别的缓存(L1、L2、L3)的特点和工作原理。CPU缓存是CPU内部的存储器,用于存储RAM中的数据和指令副本,以提高数据访问速度,减少CPU与RAM之间的速度差异。L1缓存位于处理器内部,速度最快;L2缓存容量更大,但速度稍慢;L3缓存容量最大,由所有CPU内核共享。文章还对比了DRAM和SRAM两种内存类型,解释了它们在计算机系统中的应用。
1686 1
|
6月前
|
存储 缓存 NoSQL
mybatisplus一二级缓存
MyBatis-Plus 继承并优化了 MyBatis 的一级与二级缓存机制。一级缓存默认开启,作用于 SqlSession,适用于单次会话内的重复查询;二级缓存需手动开启,跨 SqlSession 共享,适合提升多用户并发性能。支持集成 Redis 等外部存储,增强缓存能力。
|
8月前
|
缓存 Java 数据库连接
Mybatis一级缓存详解
Mybatis一级缓存为开发者提供跨数据库操作的一致性保证,有效减轻数据库负担,提高系统性能。在使用过程中,需要结合实际业务场景选择性地启用一级缓存,以充分发挥其优势。同时,开发者需注意其局限性,并做好事务和并发控制,以确保系统的稳定性和数据的一致性。
288 20
|
10月前
|
缓存 Java 数据库连接
Mybatis一级缓存、二级缓存详讲
本文介绍了MyBatis中的查询缓存机制,包括一级缓存和二级缓存。一级缓存基于同一个SqlSession对象,重复查询相同数据时可直接从缓存中获取,减少数据库访问。执行`commit`操作会清空SqlSession缓存。二级缓存作用于同一namespace下的Mapper对象,支持数据共享,需手动开启并实现序列化接口。二级缓存通过将数据存储到硬盘文件中实现持久化,为优化性能,通常在关闭Session时批量写入缓存。文章还说明了缓存的使用场景及注意事项。
331 7
Mybatis一级缓存、二级缓存详讲
|
11月前
|
缓存 Java 数据库连接
十、MyBatis的缓存
十、MyBatis的缓存
220 6
|
12月前
|
SQL Java 数据库连接
MyBatis-Plus的几种常见用法
MyBatis-Plus 为 MyBatis 提供了许多增强功能,使得开发更加便捷高效。通过基础的 CRUD 操作、条件构造器、分页插件和自动填充等功能,开发者可以显著减少代码量,提高开发效率。在实际应用中,根据具体需求选择合适的功能模块,能够更好地利用 MyBatis-Plus 提升项目开发效率。
380 22
|
12月前
|
缓存 NoSQL Java
Mybatis学习:Mybatis缓存配置
MyBatis缓存配置包括一级缓存(事务级)、二级缓存(应用级)和三级缓存(如Redis,跨JVM)。一级缓存自动启用,二级缓存需在`mybatis-config.xml`中开启并配置映射文件或注解。集成Redis缓存时,需添加依赖、配置Redis参数并在映射文件中指定缓存类型。适用于查询为主的场景,减少增删改操作,适合单表操作且表间关联较少的业务。
236 6
|
SQL Java 数据库连接
MyBatis-Plus高级用法:最优化持久层开发
MyBatis-Plus 通过简化常见的持久层开发任务,提高了开发效率和代码的可维护性。通过合理使用条件构造器、分页插件、逻辑删除和代码生成器等高级功能,可以进一步优化持久层开发,提升系统性能和稳定性。掌握这些高级用法和最佳实践,有助于开发者构建高效、稳定和可扩展的企业级应用。
737 13
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
492 4