Mybatis缓存机制

为了提升查询效率,提高用户体验,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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值