(转)mybatis一级缓存二级缓存
一級(jí)緩存
Mybatis對(duì)緩存提供支持,但是在沒有配置的默認(rèn)情況下,它只開啟一級(jí)緩存,一級(jí)緩存只是相對(duì)于同一個(gè)SqlSession而言。所以在參數(shù)和SQL完全一樣的情況下,我們使用同一個(gè)SqlSession對(duì)象調(diào)用一個(gè)Mapper方法,往往只執(zhí)行一次SQL,因?yàn)槭褂肧elSession第一次查詢后,MyBatis會(huì)將其放在緩存中,以后再查詢的時(shí)候,如果沒有聲明需要刷新,并且緩存沒有超時(shí)的情況下,SqlSession都會(huì)取出當(dāng)前緩存的數(shù)據(jù),而不會(huì)再次發(fā)送SQL到數(shù)據(jù)庫。
為什么要使用一級(jí)緩存,不用多說也知道個(gè)大概。但是還有幾個(gè)問題我們要注意一下。
1、一級(jí)緩存的生命周期有多長(zhǎng)?
a、MyBatis在開啟一個(gè)數(shù)據(jù)庫會(huì)話時(shí),會(huì) 創(chuàng)建一個(gè)新的SqlSession對(duì)象,SqlSession對(duì)象中會(huì)有一個(gè)新的Executor對(duì)象。Executor對(duì)象中持有一個(gè)新的PerpetualCache對(duì)象;當(dāng)會(huì)話結(jié)束時(shí),SqlSession對(duì)象及其內(nèi)部的Executor對(duì)象還有PerpetualCache對(duì)象也一并釋放掉。
b、如果SqlSession調(diào)用了close()方法,會(huì)釋放掉一級(jí)緩存PerpetualCache對(duì)象,一級(jí)緩存將不可用。
c、如果SqlSession調(diào)用了clearCache(),會(huì)清空PerpetualCache對(duì)象中的數(shù)據(jù),但是該對(duì)象仍可使用。
d、SqlSession中執(zhí)行了任何一個(gè)update操作(update()、delete()、insert()) ,都會(huì)清空PerpetualCache對(duì)象的數(shù)據(jù),但是該對(duì)象可以繼續(xù)使用
? ?2、怎么判斷某兩次查詢是完全相同的查詢?
mybatis認(rèn)為,對(duì)于兩次查詢,如果以下條件都完全一樣,那么就認(rèn)為它們是完全相同的兩次查詢。
2.1 傳入的statementId
2.2 查詢時(shí)要求的結(jié)果集中的結(jié)果范圍
2.3. 這次查詢所產(chǎn)生的最終要傳遞給JDBC java.sql.Preparedstatement的Sql語句字符串(boundSql.getSql()?)
2.4?傳遞給java.sql.Statement要設(shè)置的參數(shù)值
二級(jí)緩存:
MyBatis的二級(jí)緩存是Application級(jí)別的緩存,它可以提高對(duì)數(shù)據(jù)庫查詢的效率,以提高應(yīng)用的性能。
MyBatis的緩存機(jī)制整體設(shè)計(jì)以及二級(jí)緩存的工作模式
?
SqlSessionFactory層面上的二級(jí)緩存默認(rèn)是不開啟的,二級(jí)緩存的開席需要進(jìn)行配置,實(shí)現(xiàn)二級(jí)緩存的時(shí)候,MyBatis要求返回的POJO必須是可序列化的。 也就是要求實(shí)現(xiàn)Serializable接口,配置方法很簡(jiǎn)單,只需要在映射XML文件配置就可以開啟緩存了<cache/>,如果我們配置了二級(jí)緩存就意味著:
- 映射語句文件中的所有select語句將會(huì)被緩存。
- 映射語句文件中的所欲insert、update和delete語句會(huì)刷新緩存。
- 緩存會(huì)使用默認(rèn)的Least Recently Used(LRU,最近最少使用的)算法來收回。
- 根據(jù)時(shí)間表,比如No Flush Interval,(CNFI沒有刷新間隔),緩存不會(huì)以任何時(shí)間順序來刷新。
- 緩存會(huì)存儲(chǔ)列表集合或?qū)ο?無論查詢方法返回什么)的1024個(gè)引用
- 緩存會(huì)被視為是read/write(可讀/可寫)的緩存,意味著對(duì)象檢索不是共享的,而且可以安全的被調(diào)用者修改,不干擾其他調(diào)用者或線程所做的潛在修改。
實(shí)踐:
一、創(chuàng)建一個(gè)POJO Bean并序列化
由于二級(jí)緩存的數(shù)據(jù)不一定都是存儲(chǔ)到內(nèi)存中,它的存儲(chǔ)介質(zhì)多種多樣,所以需要給緩存的對(duì)象執(zhí)行序列化。(如果存儲(chǔ)在內(nèi)存中的話,實(shí)測(cè)不序列化也可以的。
package com.yihaomen.mybatis.model;import com.yihaomen.mybatis.enums.Gender; import java.io.Serializable; import java.util.List;/*** @ProjectName: springmvc-mybatis */ public class Student implements Serializable{private static final long serialVersionUID = 735655488285535299L;private String id;private String name;private int age;private Gender gender;private List<Teacher> teachers;setters&getters()....;toString(); }二、在映射文件中開啟二級(jí)緩存
<?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.yihaomen.mybatis.dao.StudentMapper"><!--開啟本mapper的namespace下的二級(jí)緩存--><!--eviction:代表的是緩存回收策略,目前MyBatis提供以下策略。(1) LRU,最近最少使用的,一處最長(zhǎng)時(shí)間不用的對(duì)象(2) FIFO,先進(jìn)先出,按對(duì)象進(jìn)入緩存的順序來移除他們(3) SOFT,軟引用,移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象(4) WEAK,弱引用,更積極的移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象。這里采用的是LRU,移除最長(zhǎng)時(shí)間不用的對(duì)形象flushInterval:刷新間隔時(shí)間,單位為毫秒,這里配置的是100秒刷新,如果你不配置它,那么當(dāng)SQL被執(zhí)行的時(shí)候才會(huì)去刷新緩存。size:引用數(shù)目,一個(gè)正整數(shù),代表緩存最多可以存儲(chǔ)多少個(gè)對(duì)象,不宜設(shè)置過大。設(shè)置過大會(huì)導(dǎo)致內(nèi)存溢出。這里配置的是1024個(gè)對(duì)象readOnly:只讀,意味著緩存數(shù)據(jù)只能讀取而不能修改,這樣設(shè)置的好處是我們可以快速讀取緩存,缺點(diǎn)是我們沒有辦法修改緩存,他的默認(rèn)值是false,不允許我們修改--><cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/><resultMap id="studentMap" type="Student"><id property="id" column="id" /><result property="name" column="name" /><result property="age" column="age" /><result property="gender" column="gender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" /></resultMap><resultMap id="collectionMap" type="Student" extends="studentMap"><collection property="teachers" ofType="Teacher"><id property="id" column="teach_id" /><result property="name" column="tname"/><result property="gender" column="tgender" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/><result property="subject" column="tsubject" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/><result property="degree" column="tdegree" javaType="string" jdbcType="VARCHAR"/></collection></resultMap><select id="selectStudents" resultMap="collectionMap">SELECTs.id, s.name, s.gender, t.id teach_id, t.name tname, t.gender tgender, t.subject tsubject, t.degree tdegreeFROMstudent sLEFT JOINstu_teach_rel strONs.id = str.stu_idLEFT JOINteacher tONt.id = str.teach_id</select><!--可以通過設(shè)置useCache來規(guī)定這個(gè)sql是否開啟緩存,ture是開啟,false是關(guān)閉--><select id="selectAllStudents" resultMap="studentMap" useCache="true">SELECT id, name, age FROM student</select><!--刷新二級(jí)緩存<select id="selectAllStudents" resultMap="studentMap" flushCache="true">SELECT id, name, age FROM student</select>--> </mapper>三、在 mybatis-config.xml中開啟二級(jí)緩存
<?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><!--這個(gè)配置使全局的映射器(二級(jí)緩存)啟用或禁用緩存--><setting name="cacheEnabled" value="true" />.....</settings>.... </configuration>四、測(cè)試
package com.yihaomen.service.student;import com.yihaomen.mybatis.dao.StudentMapper; import com.yihaomen.mybatis.model.Student; import com.yihaomen.mybatis.model.Teacher; import com.yihaomen.service.BaseTest; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.util.List;/*** * @ProjectName: springmvc-mybatis */ public class TestStudent extends BaseTest {public static void selectAllStudent() {SqlSessionFactory sqlSessionFactory = getSession();SqlSession session = sqlSessionFactory.openSession();StudentMapper mapper = session.getMapper(StudentMapper.class);List<Student> list = mapper.selectAllStudents();System.out.println(list);System.out.println("第二次執(zhí)行");List<Student> list2 = mapper.selectAllStudents();System.out.println(list2);session.commit();System.out.println("二級(jí)緩存觀測(cè)點(diǎn)");SqlSession session2 = sqlSessionFactory.openSession();StudentMapper mapper2 = session2.getMapper(StudentMapper.class);List<Student> list3 = mapper2.selectAllStudents();System.out.println(list3);System.out.println("第二次執(zhí)行");List<Student> list4 = mapper2.selectAllStudents();System.out.println(list4);session2.commit();}public static void main(String[] args) {selectAllStudent();} }?
轉(zhuǎn)載于:https://www.cnblogs.com/cat520/p/11198885.html
總結(jié)
以上是生活随笔為你收集整理的(转)mybatis一级缓存二级缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySql安装后在服务管理器里边找不到M
- 下一篇: 整理下Anytao《你必须知道的.Net