为什么使用缓存?
缓存的作用是为了减去数据库的压力,提高数据库的性能。缓存实现的原理是从数据库中查询出来的对象在使用完后不销毁,而是存储在内存(缓存)中,当再次需要获取该对象时,直接从内存中获取,不再向数据库执行select语句,减少对数据库的查询次数,提高了数据库的性能。缓存是使用Map集合存储数据。缓存是使用Map集合存储数据。
MyBtais内部缓存使用HashMap,key为hashCode+sqlid+sql语句,value为从查询出来映射生成的java对象。
一级缓存
-
一级缓存是与 SqlSession 相关联的本地缓存,它的作用范围限定在当前 SqlSession 内部。
-
同一个id,可以走缓存;不同id,即使查询的内容相同
查询顺序:
-
每当执行相同的查询语句时,MyBatis 会先从当前 SqlSession 的一级缓存中查找是否有对应的缓存数据。
-
如果一级缓存中有命中,则直接返回缓存数据,不会再发送查询请求到数据库。
生命周期:
-
一级缓存的生命周期与 SqlSession 的生命周期一致,即在同一个 SqlSession 中,多次查询相同的数据时,只有第一次会从数据库中查询,后续查询会直接从一级缓存中获取数据。
-
当 SqlSession 关闭或者提交事务时,一级缓存会被清空,所有缓存数据都会失效。
// MyBatis 的配置文件(例如:mybatis-config.xml)中不配置二级缓存 // Mapper 接口 public interface UserMapper { User selectUserById(int id); } // Mapper XML 文件 <mapper namespace="com.example.mapper.UserMapper"> <select id="selectUserById" parameterType="int" resultType="User"> select * from users where id = #{id} </select> </mapper> // 使用 Mapper 接口的代码示例 public class MyBatisExample { public static void main(String[] args) { SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSessionFactory().openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 第一次查询,命中一级缓存 User user1 = userMapper.selectUserById(1); System.out.println(user1); // 第二次查询,命中一级缓存,不会发送到数据库 User user2 = userMapper.selectUserById(1); System.out.println(user2); sqlSession.commit(); // 提交事务 } finally { if (sqlSession != null) { sqlSession.close(); } } } }
二级缓存
二级缓存是跨 SqlSession 的缓存机制,它存储在整个应用程序的内存中,由 SqlSessionFactory 管理。
查询顺序:
-
如果在当前 SqlSession 的一级缓存中未命中,MyBatis 会继续检查是否开启了二级缓存。
-
如果开启了二级缓存,并且查询的数据在二级缓存中存在,则会从二级缓存中获取数据。
-
如果二级缓存中也未命中,则 MyBatis 会发送查询请求到数据库,获取数据并同时更新一级缓存和二级缓存。
生命周期:
-
二级缓存的生命周期与整个应用程序的生命周期一致,即在应用程序关闭时才会清空。
-
当某个 SqlSession 对象对数据进行了更新(增、删、改)操作时,MyBatis 会自动刷新或者清空相关的二级缓存,保证数据的一致性和可靠性。
如何开启二级缓存
-
配置文件
-
POJO序列化,将所有的POJO类(bean)实现序列化接口java.io.Serializable。
<!-- MyBatis 的配置文件(例如:mybatis-config.xml)中配置二级缓存 --> <configuration> <settings> <setting name="cacheEnabled" value="true"/> <!-- 开启二级缓存 --> </settings> <!-- 其他配置 --> </configuration>
-
配置映射文件
在Mapper.xml映射文件中添加cache标签,表示次mapper开启二级缓存。
<!-- 表示此namespace使用二级缓存 cache标签的属性: eviction="LRU" :清除策略,默认为LRU,移除最长时间不被使用的对象。 flushInterval="60000" :刷新间隔,以毫秒为单位的合理时间量 size="512" :引用数目 readOnly="true" :只读的缓存会给所有调用者返回缓存对象的相同实例 更新操作影响: 如果将缓存设置为只读模式,在应用程序中执行的更新操作(insert、update、delete)不会更新缓存中的数据。 MyBatis 会根据更新操作自动刷新或者清空相关的缓存数据,以保证数据的一致性。 --> <!-- MyBatis 的配置文件(例如:mybatis-config.xml)中配置二级缓存 --> <configuration> <settings> <!-- 其他配置 --> </settings> <cache eviction="LRU" flushInterval="60000" readOnly="true" size="1024" type="org.mybatis.caches.ehcache.EhcacheCache"/> <!-- 其他配置 --> </configuration> <!--按照学号迭代查询--> <!-- 二级缓存 属性useCache="false",sql语句自己可以决定是否使用二级缓存 属性flushCache="false",sql语句自己可以决定是否刷新缓存,多用与新增,修改,删除语句 --> <select id="findUser" resultType="User"> SELECT * FROM t_user WHERE id in <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </select>