为了提升查询效率,提高用户体验,MyBatis提供了数据缓存支持,依据数据缓存的有效范围默认定义了一级缓存和二级缓存
一级缓存:
- 该级缓存默认开启,不能关闭;
- 该级缓存为SqlSession级别的缓存,也称为本地缓存;
体现:
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.logging.LogFactory;
import com.jd.userinfo.dao.IUserInfoDao;
import com.jd.vo.UserInfo;
/*程序的跳转方向为mybatis-config.xml——》user_info.xml——》为IUserInfoDao创造代理对象*/
public class Test{
public static void main(String[] args) {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
/*sqlSession对象表示一次数据库访问,无参,默认不提交事物,有参则提交事物*/
IUserInfoDao userInfoDao=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user=userInfoDao.select("%皮%");
System.out.println(user.size());
IUserInfoDao u=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user2=u.select("%皮%");
System.out.println(user2.size());
sqlSession.commit();
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
由代码可见,这里面共创建了两次SqlSession,程序运行中应当为链接——断开——链接——断开的步骤
但执行结果如下
根据日志显示,链接数据库只进行了一次。
这两次查询是在一个SqlSession内完成的。第二次是从一级缓存内读取执行。
以下4种情况将会导致该级缓存失效
- 在不同SqlSession中查询数据
- 相同SqlSession中查询数据,但查询条件不同
- 相同SqlSession中查询数据,但两次查询之间执行了增删改操作
- 相同SqlSession中查询数据,但第二次查询前,程序调用SqlSession对象clearCache()方法手动清除了一级缓存
第一种:在不同SqlSession中查询数据
public class Test{
public static void main(String[] args) {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
/*第一次*/
SqlSession sqlSession=sqlSessionFactory.openSession();
IUserInfoDao userInfoDao=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user=userInfoDao.select("%皮%");
System.out.println(user.size());
sqlSession.close();
/*第二次*/
sqlSession=sqlSessionFactory.openSession();
IUserInfoDao u=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user2=u.select("%皮%");
System.out.println(user2.size());
sqlSession.commit();
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
执行结果如下
第二种:相同SqlSession中查询数据,但查询条件不同。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
IUserInfoDao userInfoDao=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user=userInfoDao.select("%皮%");
System.out.println(user.size());
List<UserInfo> user2=userInfoDao.select("%J%");
System.out.println(user2.size());
sqlSession.commit();
sqlSession.close();
执行结果如下
第三种:相同SqlSession中查询数据,但两次查询之间执行了增删改操作
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
IUserInfoDao userInfoDao=sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> user=userInfoDao.select("%皮%");
System.out.println(user.size());
userInfoDao.delete("4");//删除操作
List<UserInfo> user2=userInfoDao.select("%皮%");
System.out.println(user2.size());
sqlSession.commit();
sqlSession.close();
执行结果如下
第四种 :相同SqlSession中查询数据,但第二次查询前,程序调用SqlSession对象clearCache()方法手动清除了一级缓存
sqlSession.clearCache();//写在两次查询之间
二级缓存:
该级缓存默认不开启,但如果使用二级缓存需要在每个XML映射文件中添加<cache></cache>以配置该级缓存。二级缓存可以通过在全局配置文件配置setting标签来关闭该级缓存。
- 它写于XML文件的<mapper></mapper>标签内,以namespace作为区分。
- 工作机制:通过SqlSession查询数据,这些数据将会放到当前会话的一级缓存中;如果当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的SqlSession将从二级缓存中查找数据。
- 范围跨SqlSession
cache标签属性(了解即可):
eviction:缓存回收策略:LRU – 最近最少使用的:移除最长时间不被使用的对象,默认值;FIFO – 先进先出:按对象进入缓存的顺序来移除它们;SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象;WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInterval:刷新间隔,单位毫秒,默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size:引用数目,正整数,代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly:只读,默认为false。true:只读缓存;会给所有调用者返回缓存对象的相同实例,速度快;false:读写缓存;会返回缓存对象的拷贝(通过序列化),速度慢但安全。
工作机制实例:
在xml内配置了<cache></cache>
未配置
- select标签的useCache属性用于设置是否使用二级缓存;
- insert、update、delete或select标签均有flushCache属性,其中增删改默认true,即sql执行以后,会同时清空一级和二级缓存,查询默认false