兩級緩存:
一級緩存:(本地緩存):sqlSession級別的緩存。一級緩存是一直開啟的;SqlSession級別的一個Map
數據庫同一次會話期間查詢到的數據會放在本地緩存中。以后如果需要獲取相同的數據,直接從緩存中拿,沒必要再去查詢數據庫。
一級緩存失效情況(沒有使用到當前一級緩存的情況,效果就是還需要再向數據庫發出查詢):
1、sqlSession不同。
2、sqlSession相同,查詢條件不同.(當前一級緩存中還沒有這個數據)
3、sqlSession相同,兩次查詢之間執行了增刪改操作(這次增刪改可能對當前數據有影響)
4、sqlSession相同,手動清除了一級緩存(緩存清空)
二級緩存全局緩存):基于namespace級別的緩存:一個namespace對應一個二級緩存:
工作機制:
1、一個會話,查詢一條數據,這個數據就會被放在當前會話的一級緩存中;
2、如果會話關閉;一級緩存中的數據會被保存到二級緩存中;新的會話查詢信息,就可以參照二級緩存中的內容;
3、不同namespace查出的數據會放在自己對應的緩存中(map)
效果:數據會從二級緩存中獲取
查出的數據都會被默認先放在一級緩存中。
只有會話提交或者關閉以后,一級緩存中的數據才會轉移到二級緩存中
使用:
1)、開啟全局二級緩存配置:<setting name="cacheEnabled" value="true"/>
2)、去mapper.xml中配置使用二級緩存:<cache></cache>
<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
eviction:緩存的回收策略:
LRU – 最近最少使用的:移除最長時間不被使用的對象。
FIFO – 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。
WEAK – 弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。
默認的是 LRU。
flushInterval:緩存刷新間隔,緩存多長時間清空一次,默認不清空,設置一個毫秒值
readOnly:是否只讀:
true:只讀;mybatis認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。mybatis為了加快獲取速度,直接就會將數據在緩存中的引用交給用戶。不安全,速度快
false:非只讀:mybatis覺得獲取的數據可能會被修改。mybatis會利用序列化&反序列的技術克隆一份新的數據給你。安全,速度慢
size:緩存存放多少元素;
type:指定自定義緩存的全類名,實現Cache接口即可;
3)、POJO需要實現序列化接口
和緩存有關的設置/屬性:
1)、cacheEnabled=true:false:關閉緩存(二級緩存關閉)(一級緩存一直可用的)
2)、每個select標簽都有useCache="true":
false:不使用緩存(一級緩存依然使用,二級緩存不使用)
3)、【每個增刪改標簽的:flushCache="true":(一級二級都會清除)】
增刪改執行完成后就會清楚緩存;
測試:flushCache="true":一級緩存就清空了;二級也會被清除;
查詢標簽:flushCache="false":
如果flushCache=true;每次查詢之后都會清空緩存;緩存是沒有被使用的;
4)、sqlSession.clearCache();只是清楚當前session的一級緩存;
5)、localCacheScope:本地緩存作用域(一級緩存SESSION);當前會話的所有數據保存在會話緩存中;STATEMENT:可以禁用一級緩存。 ? ? ?
第三方緩存整合:
1)、導入第三方緩存包即可;
2)、導入與第三方緩存整合的適配包;官方有;
3)、mapper.xml中使用自定義緩存
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
一、測試緩存效果
示例代碼:
接口定義:
package com.mybatis.dao;import com.mybatis.bean.Employee;public interface EmployeeMapper {public Employee getEmpById(Integer id);
}mapper定義:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.dao.EmployeeMapper"><select id="getEmpById" resultType="com.mybatis.bean.Employee">select * from tbl_employee where id=#{id}</select>
</mapper>測試代碼:
package com.mybatis.demo;import com.mybatis.bean.Employee;
import com.mybatis.dao.EmployeeMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;public class MyTest {public SqlSessionFactory getSqlSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void test() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession(true);SqlSession openSession2 = sqlSessionFactory.openSession();try {EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);Employee emp1 = mapper.getEmpById(1);System.out.println(emp1);System.out.println("---------");Employee emp2 = mapper.getEmpById(1);System.out.println(emp2);System.out.println(emp1 == emp2);System.out.println(emp1.equals(emp2));} finally {openSession.close();}}
}
二、一級緩存失效情況
示例代碼:
接口定義:
package com.mybatis.dao;import com.mybatis.bean.Employee;public interface EmployeeMapper {public Employee getEmpById(Integer id);public void addEmp(Employee emp);
}mapper定義:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.dao.EmployeeMapper"><select id="getEmpById" resultType="com.mybatis.bean.Employee">select * from tbl_employee where id=#{id}</select><insert id="addEmp">insert into tbl_employee (last_name, email, gender, d_id)values (#{lastName},#{email},#{gender},#{dept.id})</insert>
</mapper>測試代碼:
package com.mybatis.demo;import com.mybatis.bean.Department;
import com.mybatis.bean.Employee;
import com.mybatis.dao.EmployeeMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;public class MyTest {public SqlSessionFactory getSqlSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(inputStream);}//一級緩存失效情況(沒有使用到當前一級緩存的情況,效果就是還需要再向數據庫發出查詢)://1、sqlSession不同。@Testpublic void test() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession(true);SqlSession openSession2 = sqlSessionFactory.openSession();try {EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);Employee emp1 = mapper.getEmpById(1);System.out.println(emp1);System.out.println("---------");Employee emp2 = mapper2.getEmpById(1);System.out.println(emp2);System.out.println(emp1 == emp2);System.out.println(emp1.equals(emp2));} finally {openSession.close();openSession2.close();}}//2、sqlSession相同,查詢條件不同.(當前一級緩存中還沒有這個數據)@Testpublic void test2() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession(true);try {EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);Employee emp1 = mapper.getEmpById(1);System.out.println(emp1);System.out.println("---------");Employee emp2 = mapper.getEmpById(8);System.out.println(emp2);System.out.println(emp1 == emp2);System.out.println(emp1.equals(emp2));} finally {openSession.close();}}//3、sqlSession相同,兩次查詢之間執行了增刪改操作(這次增刪改可能對當前數據有影響)@Testpublic void test3() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession(true);try {EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);Employee emp1 = mapper.getEmpById(1);System.out.println(emp1);mapper.addEmp(new Employee(null, "haohao", "haohao@gmail.com", 1, new Department(2)));System.out.println("----數據添加成功----- ");Employee emp2 = mapper.getEmpById(1);System.out.println(emp2);System.out.println(emp1 == emp2);System.out.println(emp1.equals(emp2));} finally {openSession.close();}}//4、sqlSession相同,手動清除了一級緩存(緩存清空)@Testpublic void test4() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession(true);try {EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);Employee emp1 = mapper.getEmpById(1);System.out.println(emp1);openSession.clearCache();Employee emp2 = mapper.getEmpById(1);System.out.println(emp2);System.out.println(emp1 == emp2);System.out.println(emp1.equals(emp2));} finally {openSession.close();}}
}
三、二級緩存的使用
示例代碼:
接口定義:
package com.mybatis.dao;import com.mybatis.bean.Employee;public interface EmployeeMapper {public Employee getEmpById(Integer id);
}mapper定義:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.dao.EmployeeMapper"><!--eviction:緩存的回收策略:LRU – 最近最少使用的:移除最長時間不被使用的對象。FIFO – 先進先出:按對象進入緩存的順序來移除它們。SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。WEAK – 弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。默認的是 LRU。flushInterval:緩存刷新間隔緩存多長時間清空一次,默認不清空,設置一個毫秒值readOnly:是否只讀:true:只讀;mybatis認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。mybatis為了加快獲取速度,直接就會將數據在緩存中的引用交給用戶。不安全,速度快false:非只讀:mybatis覺得獲取的數據可能會被修改。mybatis會利用序列化&反序列的技術克隆一份新的數據給你。安全,速度慢size:緩存存放多少元素;type="":指定自定義緩存的全類名;實現Cache接口即可;--><cache/><select id="getEmpById" resultType="com.mybatis.bean.Employee">select * from tbl_employee where id=#{id}</select>
</mapper>測試代碼:
package com.mybatis.demo;import com.mybatis.bean.Employee;
import com.mybatis.dao.EmployeeMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;public class MyTest {public SqlSessionFactory getSqlSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(inputStream);}/*** 使用:* 1)、開啟全局二級緩存配置:<setting name="cacheEnabled" value="true"/>* 2)、去mapper.xml中配置使用二級緩存:<cache></cache>** <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>* eviction:緩存的回收策略:* LRU – 最近最少使用的:移除最長時間不被使用的對象。* FIFO – 先進先出:按對象進入緩存的順序來移除它們。* SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。* WEAK – 弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。* 默認的是 LRU。* flushInterval:緩存刷新間隔,緩存多長時間清空一次,默認不清空,設置一個毫秒值* readOnly:是否只讀:* true:只讀;mybatis認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。mybatis為了加快獲取速度,直接就會將數據在緩存中的引用交給用戶。不安全,速度快* false:非只讀:mybatis覺得獲取的數據可能會被修改。mybatis會利用序列化&反序列的技術克隆一份新的數據給你。安全,速度慢* size:緩存存放多少元素;* type:指定自定義緩存的全類名,實現Cache接口即可;* <p>* 3)、POJO需要實現序列化接口*/@Testpublic void test() throws IOException {SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession openSession = sqlSessionFactory.openSession();SqlSession openSession2 = sqlSessionFactory.openSession();try {//1、EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);Employee emp01 = mapper.getEmpById(1);System.out.println(emp01);openSession.close();//第二次查詢是從二級緩存中拿到的數據,并沒有發送新的sqlEmployee emp02 = mapper2.getEmpById(1);System.out.println(emp02);openSession2.close();} finally {}}
}
?