Mybatis笔记本(3)
13、mybatis缓存
说明: 缓存指的是把一些常用的数据,保存到一个可以高速读取的缓冲区中。方便程序在频繁读取的时候,可以快速的取出数据。这就叫做缓存。
一级缓存指的是,这些缓存的数据,在同一个SqlSession中多次SQL操作都可以获取。
二级缓存指的是,这些缓存的数据。在同一个Mapper中有一个cache缓存对象。多个SqlSession对象可以共享这些数据。
mybatis的一级缓存
MyBatis的一级缓存默认开启。同一个SqlSession中查询,可以从一级缓存中取数据。
一级缓存的管理
缓存失效的四种情况:
1.不在同一个SqlSession对象中
2.执行语句的参数不同。缓存中也不存在数据。
3.执行增,删,改,语句,会清空掉缓存
4.手动清空缓存数据
mybatis的二级缓存
二级缓存的图解示意
二级缓存的使用:
myBatis的二级缓存默认是不开启的。我们需要在mybatis的核心配置文件中配置setting选项 和 在Mapper的配置文件中加入cache标签。并且需要被二级缓存的对象必须要实现java的序列化接口。
一:配置全局的setting
<!-- 启用二级缓存 -->
<setting name="cacheEnabled" value="true"/>
二:在需要使用二级缓存的Mapper配置文件中加入cache标签
<!-- cache标签配置二级缓存 -->
<cache></cache>
三:需要二级缓存的数据对象必须要实现序列化接口java.io.Serializable
在Mapper配置文件的定义select查询语句的标签中,可以给某个select查询语句定义不使用二级缓存。
默认情况下,在所有的insert。update。delete标签中,都有flushCache=”true”。这样的属性。
表示当要执行增,删,改语句的时候,都需要清空缓存中的数据。清空之后,再次的查询就不会从二级缓存中获取数据。
这样做的好处是为了避免出现脏读的情况。
<cache></cache>标签的介绍和说明
默认的<cache/>标签的作用:
1、映射语句文件中的所有 select 语句将会被缓存。
2、射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
3、缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
4、根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
5、缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
6、缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
cache标签示例解析:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
eviction 属性表示缓存策略。
· LRU – 最近最少使用的:移除最长时间不被使用的对象(这是默认策略)。
· FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
· SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
· WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval 属性表示间隔多长时间刷新一下缓冲区,清理一下溢出的数据。以毫秒为单位。
size 属性表示缓存中可以保存多少个对象。默认是1024。
readOnly 属性表示是否只读。如果设置为true。表示缓存中只有一个对象。如果设置为false(默认为false)每次取出来都会反序列化拷贝一份。
type 属性表示自定义二级缓存对象。
EhCache缓存的使用
EhCache缓存介绍:
EhCache 是一个专业的纯Java的进程缓存框架。具有快速、精干等特点,是Hibernate中默认的CacheProvider缓存提供者。
由于MyBatis中定义了Cache缓存接口极大的方便了我们对缓存的自定义切换和扩展。
整合EhCache到MyBatis的步骤:
1.导入ehcache的包。以及整合包。
2.编写ehcache.xml配置文件
<?xmlversion="1.0"encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径-->
<diskStore path="D:\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候,移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
3.配置cache标签的type属性
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
缓存的使用顺序说明:
1、当我们执行一个查询语句的时候。mybatis会先去二级缓存中查询数据。如果二级缓存中没有。就到一级缓存中查找。
2、如果二级缓存和一级缓存都没有。就发sql语句到数据库中去查询。
3、查询出来之后马上把数据保存到一级缓存中。
4、当SqlSession关闭的时候,会把一级缓存中的数据保存到二级缓存中。
mybatis ****
MyBatis****,简称MBG。是一个专门为MyBatis框架使用者定制的代码生成器。可以快速的根据表生成对应的映射文件,接口,以及Bean类对象。
在Mybatis中,有一个可以自动对单表生成的增,删,改,查代码的插件。
叫 mybatis-generator-core-1.3.2。
它可以帮我们对比数据库表之后,生成大量的这个基础代码。
这些基础代码有:
1、数据库表对应的javaBean对象
2、这些javaBean对象对应的Mapper接口
3、这些Mapper接口对应的配置文件
mybatis的源码分析
mybatis框架中有四大对象:
· Executor 负责update, query, flushStatements, commit,rollback, getTransaction, close, isClosed
· ParameterHandler 负责getParameterObject, setParameters
· ResultSetHandler 负责handleResultSets, handleOutputParameters
· StatementHandler 负责prepare, parameterize, batch, update,query
过滤器相关:
InterceptorChain 过滤器链 管理管理和调用全部的过滤器执行
Interceptor 过滤器 负责拦截Executor、ParameterHandler、ResultsetHandler、StatementHandler
mybatis的分页插件pageHelper使用
1、先导入mybatis-pageHelper的jar包。
2、到mybatis-config.xml核心配置文件中配置分页的拼接器。
<plugins>
<!--com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor"> </plugin>
</plugins>
3、使用mybatis-pageHelper示例代码:
@Test
publicvoid testQueryUsers() {
SqlSession session = sqlSessionFactory.openSession();
try {
Page<User> page =PageHelper.startPage(1, 5);
UserMapper userMapper =session.getMapper(UserMapper.class);
List<User> list =userMapper.queryUsers();
System.out.println("当前页:" +page.getPageNum());
System.out.println("总页数:" +page.getPages());
System.out.println("每页显示数量:" +page.getPageSize());
System.out.println("总记录数:" +page.getTotal());
System.out.println("当前页数据:" +page.getResult());
System.out.println(page);
for (User user : list) {
System.out.println(user);
}
} finally {
session.close();
}
}
4、测试结果:
PageInfo类的使用。
PageInfo 类是专门给分页使用的一个类。可以方便的帮我们计算出需要显示的页码。使用起来也很简单。
使用示例:
@Test
publicvoid testQueryUsers() {
SqlSession session= sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
PageHelper.startPage(5, 2);
List<User> list =userMapper.queryUsers();
PageInfo<User>pageInfo = newPageInfo<>(list, 5);
System.out.println("当前页:" +pageInfo.getPageNum());
System.out.println("总页数:" +pageInfo.getPages());
System.out.println("每页显示数量:" +pageInfo.getPageSize());
System.out.println("总记录数:" +pageInfo.getTotal());
// 遍历当前页数据
for (User user : list) {
System.out.println(user);
}
// 遍历分页条页码
System.out.print("分页条,页码是:");
for (int i :pageInfo.getNavigatepageNums() ) {
System.out.print( i + "\t" );
}
System.out.println();
} finally {
session.close();
}
}
测试的结果