MyBatis(五)关于MyBatis中延迟加载和缓存
一.延迟加载
1.什么是延迟加载?
延迟加载(lazy load)是(也称为懒加载),延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作
可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。
2.延迟加载分三种
(1)直接加载(执行完主加载后马上执行关联对象的查询)
lazyLoadingEnabled=false,(默认情况下)
aggressiveLazyLoading=true
(2)侵入式延迟加载(执行主加载是,不会执行关联对象的查询)
lazyLoadingEnabled=true
lazyLoadingEnabled=true
(3)深度延迟
lazyLoadingEnabled=true
lazyLoadingEnabled=false
配置延迟加载
<settings> <!--<setting name="autoMappingBehavior" value="NONE"/>--> <!--延迟加载--> <!--<setting name="lazyLoadingEnabled" value="true"></setting> <setting name="aggressiveLazyLoading" value="false"></setting>--> <setting name="cacheEnabled" value="true"></setting> </settings>
二.缓存(一级缓存和二级缓存)
1.什么是缓存?
缓存就是数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行
现在我们探讨的缓存是在内存中,缓存数据保存在内存中
查询缓存:应用服务器内存中,主要是为了提高查询访问速度
2.缓存的分类
MyBatis根据缓存区的作用于与申明周期分为:一级缓存和二级缓存
无论是一级缓存还是二级缓存都是按照namespace进行分别存放
不同之处在于SqlSessiion的关闭一级缓存也会不存在,一级缓存在同一线程内有效,二级缓存是在不同SqlSession中共享数据
3.一级缓存的存在性证明
Mybatis缓存的底层实现的Map,他的查询依据是:sql的id+sql语句
增删改操作会对缓存造成影响,会清空一级缓存
首先,在大配置中设置
<setting name="cacheEnabled" value="true"></setting>
//证明一级缓存的存在性 @Test public void firstLevelHasExist(){ SqlSession sqlSession = MyBatisUtil.getSession(); IDeptDao mapper = sqlSession.getMapper(IDeptDao.class); Dept dept = mapper.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept.getDeptName()); //证明一级缓存的存在性 System.out.println("分割线======================="); Dept dept2 = mapper.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept2.getDeptName()); sqlSession.close(); }
运行结果如下
只发送了一次sql语句
现在添加一个对象
@Test public void firstLevelHasExist(){ SqlSession sqlSession = MyBatisUtil.getSession(); IDeptDao mapper = sqlSession.getMapper(IDeptDao.class); Dept dept = mapper.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept.getDeptName()); //证明一级缓存的存在性 Dept d1=new Dept(); d1.setDeptName("运营部"); mapper.addDept(d1); System.out.println("分割线======================="); Dept dept2 = mapper.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept2.getDeptName()); sqlSession.close(); }
发送了两次sql语句,所以增删改会清空缓存
4.二级缓存
//证明二级缓存的存在性 @Test public void secondLevelHasExist(){ SqlSession sqlSession = MyBatisUtil.getSession(); IDeptDao mapper = sqlSession.getMapper(IDeptDao.class); Dept dept = mapper.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept.getDeptName()); sqlSession.close(); System.out.println("===========二级缓存============"); SqlSession sqlSession2 = MyBatisUtil.getSession(); IDeptDao mapper2 = sqlSession2.getMapper(IDeptDao.class); Dept dept2 = mapper2.getEmpByDeptNoMultiSQL(1); System.out.println("部门名称:"+dept2.getDeptName()); sqlSession2.close(); }
这是两个线程
4.配置第三方缓存EhCache
第一步:首先要引入jar包
<!--Ecache的核心包--> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.4</version> </dependency> <!--MyBatis整合EhCache的包--> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency>
第二步:在小配置(接口对应的xml文件)中添加
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
在这个节点中还有其他的一些属性,
<!--
eviction:默认值是LRU
flushInterval:刷新时间 默认不刷新,调用语句时才刷新
size:可以设置的最多的缓存,默认值1024
readOnly:默认值是false
-->
第三步:在resources目录下写入文件ehcache.xml文件
文件中的内容,直接复制下面的代码就可以
<ehcache> <!-- Sets the path to the directory where cache .data files are created. If the path is a Java System Property it is replaced by its value in the running VM. The following properties are translated: user.home - User's home directory user.dir - User's current working directory java.io.tmpdir - Default temp file path --> <diskStore path="java.io.tmpdir"/> <!--Default Cache configuration. These will applied to caches programmatically created through the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!--Predefined caches. Add your cache configuration settings here. If you do not have a configuration for your cache a WARNING will be issued when the CacheManager starts The following attributes are required for defaultCache: name - Sets the name of the cache. This is used to identify the cache. It must be unique. maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <!-- Sample cache named sampleCache1 This cache contains a maximum in memory of 10000 elements, and will expire an element if it is idle for more than 5 minutes and lives for more than 10 minutes. If there are more than 10000 elements it will overflow to the disk cache, which in this configuration will go to wherever java.io.tmp is defined on your system. On a standard Linux system this will be /tmp" --> <cache name="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <!-- Sample cache named sampleCache2 This cache contains 1000 elements. Elements will always be held in memory. They are not expired. --> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> <!-- Place configuration for your caches following --> </ehcache>