Mybatis | 08 Mybatis缓存
Mybatis缓存
1. 缓存相关概念
简述,后续补充
1.1 什么是缓存
缓存指的是存在于内存中的临时数据
1.2 缓存的优势
在第一次获取数据后就将数据存在内存中:
- 可以减少和数据库的交互次数
- 提高执行效率
1.3 适用于缓存的情况
-
经常查询的数据:要经常使用否则就会浪费内存空间
-
不经常改变的数据:保证数据和数据库中的一致
-
数据的正确性对最终结果影响不大的数据
Tips 1.1:数据的正确性的影响
数据的变化可能导致缓存中的数据可能与数据库中的不同,影响数据正确性而获得错误的数据
数据正确性对最终结果影响较大的情况大多是查询一些时效性较高的数据时
例如:银行汇率、商品的库存等
2. Mybatis缓存的使用
2.1 程序代码
- 用户实体类
package org.example.domain;
//使用二级缓存要可序列化
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//省略get和set方法
}
- 用户DAO层接口
package org.example.dao;
public interface IUserDao{
//查询所有用户
List<User> findAllUser();
//通过用户ID查询用户
User findUserById(Integer userId);
//更新用户信息
void updateUser(User user);
}
- 用户映射文件
<!--头文件省略-->
<mapper namespace="org.example.dao.IUserDao">
<select id="findAllUser" resultType="user">
select * from user;
</select>
<select id="findUserById" parameterType="INT" resultType="user">
select * from user where id=#{id};
</select>
<select id="updateUser" parameterType="user">
update user set username=#{username} where id=#{id};
</select>
</mapper>
- 测试方法
public class UserTest{
InputStream in = null;
SqlSessionFactory factory = null;
SqlSession session = null;
IUserDao userDao = null;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
}
@After
public void destroy() throws IOException {
session.commit();
session.close();
in.close();
}
}
2.2 一级缓存
2.2.1 一级缓存定义
Mybatis一级缓存指Mybatis中SqlSession对象级别的缓存
Tips :一级缓存细节
- 执行查询后,查询结果会以对象的映射存入到SqlSession的一块区域中(Map结构)
- 当再次查询时会查询SqlSession中是否有缓存数据,有就直接使用,没有在进行查询
2.2.3 一级缓存测试
- 测试方法
//省略申请资源和释放资源的部分 和UserTest中一致
@Test
public void firstLevelCacheTest(){
//两次查询
User user1 = userDao.findUserById(41);
System.out.println(user1);
User user2 = userDao.findUserById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
- 测试结果
2.2.4 一级缓存的清除
三种清空一级缓存的方式
- close( ):关闭SqlSession对象一级缓存失效
- clearCache( ):调用清空缓存方法清空一级缓存
- commit( ):通过提交增删改操作更新数据库后会自动清空一级缓存
- close( )清除测试
@Test
public void firstLevelCacheClearTest(){
User user1 = userDao.findUserById(41);
System.out.println(user1);
//关闭SqlSession
session.close();
//重新获取SqlSession
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
User user2 = userDao.findUserById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
- 测试结果
- clearCache( )清除测试
@Test
public void firstLevelCacheClearTest(){
User user1 = userDao.findUserById(41);
System.out.println(user1);
//清空缓存方法
session.clearCache();
User user2 = userDao.findUserById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
- 测试结果
- commit( )清除测试
@Test
public void firstLevelCacheClearTest(){
User user1 = userDao.findUserById(41);
System.out.println(user1);
//更新数据库
user1.setUsername("abc");
userDao.updateUser(user1);
User user2 = userDao.findUserById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
- 测试结果
2.3 二级缓存
2.3.1 二级缓存定义
二级缓存是跨SqlSession的
-
指Mybatis中SqlSessionFactory对象级别的缓存,由factory创建的所有SqlSession共享缓存
-
也可以理解为Mapper映射级别的缓存,操作同一个映射的SQL语句的SqlSession共享缓存
Tips:二级缓存的细节
二级缓存存放的是查询结果的数据而不是对象
再次查询时,如果有缓存数据就会用这些数据去创建对象而不用再次查询
使用二级缓存时相应的类要可以序列化
2.3.2 二级缓存的开启
- 开启Mybatis框架对二级缓存的支持
在主配置文件中使用**setting标签设置cacheEnable属性**开启二级缓存
<!--头文件橙略-->
<configruation>
<!--其他部分的配置省略-->
<settings>
<setting name="cacheEnabled" value="true"></setting>
</settings>
</configruation>
Tips:CacheEnabled属性默认值时true
- 开启映射文件对二级缓存的支持
在映射文件中使用cache标签开启二级缓存
<mapper namespace="org.example.dao.IUserDao">
<cache></cache>
<!--其他部分配置省略-->
</mapper>
- 开启当前的操作对二级缓存的支持
在select标签中设置useCache的属性值
<select id="findUserById" parameterType="INT" resultType="user" useCache="true">
select * from user wher id=#{id};
</select>
Tips:userCache默认值时true,可以省略配置
2.3.3 二级缓存测试
- 测试方法
//省略申请资源和释放资源的部分 和UserTest中一致
@Test
public void secondLevelCacheTest(){
//两次查询
SqlSession session1 = factory.openSession();
IUserDao userDao1 = session1.getMapper(IUserDao.class);
User user1 = userDao1.findUserById(41);
System.out.println(user1);
session1.close();
SqlSession session2 = factory.openSession();
IUserDao userDao2 = session2.getMapper(IUserDao.class);
User user2 = userDao2.findUserById(41);
System.out.println(user2);
session2.close();
System.out.println(user1 == user2);
}
- 测试结果
2.3.4 二级缓存的清除
commit( ):通过提交增删改操作到数据库清空二级缓存
- 清除测试
//省略申请资源和释放资源的部分 和UserTest中一致
@Test
public void secondLevelCacheTest(){
SqlSession session1 = factory.openSession();
IUserDao userDao1 = session1.getMapper(IUserDao.class);
User user1 = userDao1.findUserById(41);
System.out.println(user1);
//更新数据库
user1.setUsername("abc");
userDao1.updateUser(user1);
session1.commit();
session1.close();
SqlSession session2 = factory.openSession();
IUserDao userDao2 = session2.getMapper(IUserDao.class);
User user2 = userDao2.findUserById(41);
System.out.println(user2);
session2.close();
System.out.println(user1 == user2);
}
- 测试结果