一、缓存:
缓存分多种,初学者可能需要先区分清楚,服务器具备缓存、浏览器也具备缓存,java技术中,Mybatis框架下,具备特定的缓存机制。
缓存是指存在内存中的临时数据,使用缓存能够减少和数据库交互的次数,提高效率。缓存的作用体现在减少IO的次数。
二、mybatis中的缓存:
在mybatis中,当程序发起数据库的访问,返回结果时,会把本次结果存入到内存或某种缓存介质中,当下次遇到同样条件的SQL时,mybatis会不再进行二次的数据库交互,而是从缓存中直接读取结果返回,从而减少服务器的压力。
从上面的描述机制可以推出,缓存是针对查询SQL(也就是select,其他的缓存同理)。因为增删改,条件或传入参数通常都产生变化。
在mybatis中,包括一级缓存和二级缓存(CPU的缓存会有三级,不同类别的缓存也会有多种),因为个人对缓存的理解不是很深刻,概念与区别先记录下来,以免混淆。
1、一级缓存(SQL级别,相同的SELECT语句以及相同的SQLSession对象)
mybatis默认开启一级缓存,一级缓存主要指SQLSession(SQLSession主要用于执行增删改查SQL),一级缓存作用域是SQLSession(作用域也要清楚,即同一个SQLSession对象下的操作,假如不同的SQLSession操作同一条SELECT语句,都是第一次查询的情况下,则不会走缓存)。
在同一个SQLSession中执行同样的SQL语句,第一次会从数据库查询,写入缓存,第二次就会直接从缓存中取出。如果发生增删改操作,会清空缓存;而每次的查询都是先从SQLSession中寻找记录,当记录不存在则去数据库中查询。
一级缓存的测试例子比较简单,这里不多写,可以直接新建项目,集成好mybatis框架,随便通过一个test,开启SQL执行日志的打印,分2次执行同一个SELECT语句的调用,打印至控制台去进行一次数据读取打印出来都可以测试。
这个是mybatis配置文件开启日志设置(百度来的,有问题再找办法,搜一下应该有的):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 打印sql日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
当你的控制台在2次执行中,只打印一次语句,可以证明一级缓存的读取。
· 一级缓存的生命周期:
1)mybatis在开启一个数据库会话时,会新建一个SQLSession对象,SQLSession对象中,会有一个新的Executor对象。Executor对象中持有一个PerpetualCache对象;当会话结束时,SQLSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉;
2)如果SQLSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
3)如果SQLSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍旧可用。
4)SQLSession中执行任何一个update操作(增删改),都会清空PerpetualCache对象的数据,但是该对象可以继续使用。
2、二级缓存(Mapper级别,相同的SELECT语句,不同SQLSession对象)
Mybatis的二级缓存是Mapper级别的缓存。作用域是同一个SqlSessionFactory对象,跨SqlSession对象。二级缓存是需要手动配置启用。
引用博主的一张图阐述下二级缓存的工作模式:
启用二级缓存的条件:
1)在配置文件中设置cacheEnabled为true:默认不配置为true
<setting name="cacheEnabled" value="true">
2)在需要使用的Mapper文件中,添加<cache />
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxMapper">
<!-- 需要在对应的Mapper.xml文件中添加以下标签。用来表示本mapper使用该二级缓存。-->
<cache/>
<select id="query" parameterType="integer" resultType="">
select * from xxx
</select>
</mapper>
3)使用二级缓存的实体类对象必须是可序列化的,即需要该对象实现java.io.Serializable接⼝:
public class Emp implements Serializable {}
4)SqlSession对象关闭或提交之后,⼀级缓存中的数据才会被写⼊到⼆级缓存当中。此时⼆级缓存才可⽤。