Mybatis入门笔记(四)
——2018年11月16日
1.Mybatis的缓存机制:
mybatis是常见的java数据库的访问层框架,mybatis提供的缓存机制减轻数据库压力,提高数据库性能;在大多数情况下使用的mybatis的默认缓存配置,也就是mybatis的一级缓存。、
mybatis的缓存机制分为两级:一级缓存和二级缓存
一级缓存:sqlSession级别的缓存,缓存的数据只是在sqlSession内有效
二级缓存:是mapper级别的缓存,同一个那么space公用这一个缓存,所以对sqlSession是共享的。
通过介绍可能还不是很懂,现在就从代码方面来介绍:
一级缓存:
Mybatis的缓存是sqlsession级别的缓存,在操作数据库的时候需要创建sqlsession会话对象,在对象中有一个Hashmap用于储存数据,此HashMap是当前会话对象私有的,别的sqlsession会话对象无法访问。
当在一个sqlsession操作相同的sql时:
Log4j打印的日志:只向数据库发送了一条sql第二次就直接使用缓存打印了第二条记录,大家都知道,如果没有缓存是会向数据库发送两次sql的。
具体执行流程:
- 第一次执行查询的时候将数据写入sqlSession内的HashMap中缓存起来
- 第二次执行查询时就直接从缓存中查询数据,如果select相同切传参一样,那么就能从缓存中返回数据,从而提高了效率。
值得注意的是:
- 如果sqlSession执行了DML操作(insert,update,delete),并commit了,那么mybatis就会清空当前SqlSession缓存中的所有缓存数据,这样可以保证缓存中存的数据永远和数据库一致,避免出现脏读
- Mybatis默认开启一级缓存,不需要配置。
二级缓存:
二级缓存是mapper级别的缓存,也就是同一个namespace的mapper.xml,当多个sqlSession使用同一个Mapper操作数据库的时候,得到的数据会缓存在同一个二级缓存区域
二级缓存默认时开启的
在mapper.xml中配置:
若想禁用当前sql语句的二级缓存,只需添加userCache属性就行。
使用二级缓存两种方式:
1.添加maven包依赖:
- 在classpath下配置ehcache.xml文件:
<ehcache>
<!--
指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.
-->
<diskStore path="G:\mybatiscache"/>
<!--
设置缓存的默认数据过期策略
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--
设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域
缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。
如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。即:<defaultCache.../>
Hibernate 在不同的缓存区域保存不同的类/集合。
对于类而言,区域的名称是类名。如:com.atguigu.domain.Customer
对于集合而言,区域的名称是类名加属性名。如com.atguigu.domain.Customer.orders
-->
<!--
name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字
maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目
eternal: 设置对象是否为永久的, true表示永不过期, 此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地 处于空闲状态。
timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。如果此值为0,表示对象可以无限期地存在于缓存中.
该属性值必须大于或等于 timeToIdleSeconds 属性值
overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
-->
<cache name="com.atguigu.hibernate.entities.Employee"
maxElementsInMemory="1"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="com.atguigu.hibernate.entities.Department.emps"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>
然后测试Test:
注意:使用完一个Sqlsession后需关闭。
Log4j打印日志:
说明缓存开启成功。
第二种方式就是实现Serializable接口