泗阳网站建设,用js做自适应网站,域名交易网站源代码下载,wordpress 实现申请友情链接links其实缓存字面的意思就是将一些内容缓存下来#xff0c;等下次使用的时候可以直接调用#xff0c;通过数据库得到数据#xff0c;有时候会使用相同的数据#xff0c;所以mybatis自然也支持缓存。
而mybatis按照缓存的效果可以分两大类#xff1a;一级缓存和二级缓存。
一…其实缓存字面的意思就是将一些内容缓存下来等下次使用的时候可以直接调用通过数据库得到数据有时候会使用相同的数据所以mybatis自然也支持缓存。
而mybatis按照缓存的效果可以分两大类一级缓存和二级缓存。
一级缓存
其实一级缓存是SqlSession级别通过SqlSession查询的数据会被缓存下次查询相同的数据就会从缓存中直接获取不会从数据库中重写访问。
还是老规矩进行代码演示
ListStudent getStudent();select idgetStudent resultTypeStudentSELECT sid , sname , sage , ssex , gid FROM testmybatis.student/select然后调用的时候不关闭SqlSession然后连续调用getStudent() System.out.println( -------------------- 第一次 studentMapper.getStudent());System.out.println( -------------------- 第二次 studentMapper.getStudent()); 可以看出sql语句只是调用了一次但是还是得到了数据。
但是一级缓存也是会失效的其中有四种情况 不同的SqlSession对应不同一级缓存比如例子一直说用的同一个sqlsession也没有关闭sqlsession重写创建了一个。 同一个SqlSession但是两次查询的条件不同甚至是操作相同但是方法名不同,也不会调用缓存可以看下演示 ListStudent getStudent();ListStudent getStudent1();select idgetStudent resultTypeStudentSELECT sid , sname , sage , ssex , gid FROM testmybatis.student/selectselect idgetStudent1 resultTypeStudentSELECT sid , sname , sage , ssex , gid FROM testmybatis.student/select然后调用 System.out.println( -------------------- 第一次 studentMapper.getStudent());System.out.println( -------------------- 第二次 studentMapper.getStudent());System.out.println( -------------------- 另一个第一次 studentMapper.getStudent1());System.out.println( -------------------- 第三次 studentMapper.getStudent());可以看出哪怕同一个sqlsession其一样的sql语句通过两个不同方法也不会调用缓存因为sql语句执行了两次。当然其也不会影响已缓存是数据。 同一个sqlsession同一个查询在两者依次执行期间执行了任何依次增改操作。 来实体体验一把 ListStudent getStudent();void deleteStudent();select idgetStudent resultTypeStudentSELECT sid , sname , sage , ssex , gid FROM testmybatis.student/selectdelete iddeleteStudent!--这里删除一个不存在的数据 --delete from testmybatis.student where sid100/deleteSystem.out.println( -------------------- 第一次 studentMapper.getStudent());studentMapper.deleteStudent();System.out.println( -------------------- 第二次 studentMapper.getStudent());可以看出其删除无论是否存在 同一个SqlSession两次执行同一个查询中介执行了手动清楚缓存。 System.out.println( -------------------- 第一次 studentMapper.getStudent());
// 调用clearCache() 手动清楚了缓存sqlSession.clearCache();System.out.println( -------------------- 第二次 studentMapper.getStudent());二级缓存
二级缓存是SqlSessionFactory级别的同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存此后执行相同的查询语句数据就会从缓存中得到。
启用的条件
在核心配置文件中加入配置setting namecacheEnabledvaluetrue /在映射文件中加入cache /查询的数据转换的实体类类型必须实现序列化接口Serializable。SqlSession在关闭或者提交以后二级缓存才会有效。
还是老规矩进行演示:
前提在核心配置文件mybatis-config.xml中配置 settingssetting namecacheEnabled valuetrue //settings然后再映射文件中添加 cache/cache实体类需要实现序列化接口
public class Student implements Serializable现在开始演示 SqlSession sqlSession sqlSessionFactory.openSession(true);
// 这个通过代理模式传入什么类返回什么类StudentMapper studentMapper sqlSession.getMapper(StudentMapper.class);System.err.println( -------------------- 第一次 sqlSession -- getStudent studentMapper.getStudent());// 不关闭的话sqlSession.close();SqlSession sqlSession1 sqlSessionFactory.openSession();StudentMapper studentMapper1 sqlSession1.getMapper(StudentMapper.class);System.err.println( -------------------- 第一次 sqlSession1 -- 方法名为 getStudent studentMapper1.getStudent());System.err.println( -------------------- 第一次 sqlSession1 -- 方法名为 getStudent1 studentMapper1.getStudent1());studentMapper1.deleteStudent();System.err.println( -------------------- 第二次 sqlSession1 -- 执行deleteStudent后调用 getStudent studentMapper1.getStudent());sqlSession1.close();可以看出了只要删除或者修改了数据库无论是一级缓存还是二级缓存都会同时失效。
这个又有一个疑问了那就是一级缓存和二级缓存的查询顺序是什么
先查询二级缓存没有再查询二级缓存如果还没有再查询数据库。
为什么会这样因为二级缓存覆盖的更广一级缓存中没有但是在二级缓存中减少去数据库中取数的频次。
补充--------二级缓存的配置
其实再映射文件中可以配置一些属性
看一下官网举出的例子
cacheevictionFIFOflushInterval60000size512readOnlytrue/eviction 属性是缓存回收策略默认是LRU。
这个更高级的配置创建了一个 FIFO 缓存每隔 60 秒刷新最多可以存储结果对象或列表的 512 个引用而且返回的对象被认为是只读的因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用的清除策略有
LRU – 最近最少使用移除最长时间不被使用的对象。FIFO – 先进先出按对象进入缓存的顺序来移除它们。SOFT – 软引用基于垃圾回收器状态和软引用规则移除对象。WEAK – 弱引用更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
flushInterval刷新间隔属性可以被设置为任意的正整数设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置也就是没有刷新间隔缓存仅仅会在调用语句时刷新。
size引用数目属性可以被设置为任意正整数要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
readOnly只读属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会通过序列化返回缓存对象的拷贝。 速度上会慢一些但是更安全因此默认值是 false。
当然还有一个属性没有写那就是type其在使用第三方的缓存的时候使用因为有些第三方的缓存的功能会更强大所以有时候会使用第三方缓存这个就下一篇具体聊。