學(xué)習(xí)記錄之Mybatis框架
Mybatis框架解決了數(shù)據(jù)庫編程相關(guān)的問題,主要是簡化了數(shù)據(jù)庫編程。
當(dāng)使用Mybatis框架實現(xiàn)數(shù)據(jù)庫編程時,只需要:
1.定義數(shù)據(jù)操作功能的抽象方法(此抽象方法必須在接口中)
2.配置以上抽象方法映射的SQL語句
Mybatis框架在實現(xiàn)過程中,會自動生成各接口的代理對象,所以,開發(fā)人員并不需要關(guān)注接口的實現(xiàn)問題。
使用Mybatis框架:
在Spring Boot項目中,當(dāng)需要使用Mybatis框架實現(xiàn)數(shù)據(jù)庫編程時,需要添加:
1.mybatis-spring-boot-starter
2.數(shù)據(jù)庫的依賴,例如mysql-connector-java
所以,在
pom.xml
中添加:
由于添加以上依賴后,Spring Boot在啟動時就會讀取連接數(shù)據(jù)庫的配置信息,如果未配置,則啟動報錯且失敗,需要在src/main/resources
下的application.properties
中添加必要的配置:
提示:以上配置中,屬性名稱是固定,以上示例值是錯誤值,但是,啟動Spring Boot只是加載以上配置,并不會執(zhí)行連接,所以,配置值錯誤并不影響啟動項目。
連接數(shù)據(jù)庫的配置:
在Spring Boot項目中,src/main/resources
下的application.properties
是默認(rèn)的配置文件,項目在啟動時,Spring Boot會自動從此文件中讀取相關(guān)的配置信息。
在許多配置過程中,需要在application.properties
中的配置的屬性的名稱是固定的!
在配置數(shù)據(jù)庫的連接信息時,至少需要配置spring.datasource.url
、spring.datasource.username
、spring.datasource.password
這3個屬性,分別表示連接數(shù)據(jù)庫的URL、登錄數(shù)據(jù)庫的用戶名、登錄數(shù)據(jù)庫的密碼
為了檢驗配置值是否正確,可以在src/test/java
下默認(rèn)的包下創(chuàng)建DatabaseConnectionTests
測試類,在測試類中編寫測試方法,以嘗試連接數(shù)據(jù)庫,即可檢驗:
關(guān)于設(shè)計數(shù)據(jù)表:
關(guān)于id:
阿里巴巴的建議是:每張表都應(yīng)該有id
字段,且是bigint unsigned
類型,其中,bigint
對應(yīng)Java中的long
類型,unsigned
表示“無符號位”,將使得此字段值不會出現(xiàn)負(fù)數(shù),且取值區(qū)間是原正數(shù)的2倍……以tinyint
為例,沒有添加unsigned
時,取值區(qū)間是[-128, 127],添加unsigned
以后,取值區(qū)間是[0, 255]。
當(dāng)把id
的類型設(shè)置為bigint
時,理論上id值足夠使用,即使不添加unsigned
也不會出現(xiàn)id值不夠用的情況,但仍推薦添加,其目的是為了表現(xiàn)語義。
關(guān)于編碼:
應(yīng)該在創(chuàng)建表時指定編碼,創(chuàng)建庫時可以不指定編碼。
在MySQL?/?MariaDB強(qiáng)烈推薦使用utf8mb4
。
關(guān)于字符串的字段類型:
如果某個字符串類型的字段的值的長度變化可能較大,應(yīng)該使用varchar
類型,例如用戶名,如果某個字符串類型的字段的值的長度變化不大,應(yīng)該使用char
類型。
注意:某些數(shù)據(jù)可能是純數(shù)字的,但并不具備算術(shù)運(yùn)算含義,也應(yīng)該使用字符串類型,不要使用數(shù)值類型。
在使用varchar
時,指定的長度一定是“大于必要長度”的標(biāo)準(zhǔn),例如,現(xiàn)行的標(biāo)準(zhǔn)是“用戶名最多15個字符”,則建議設(shè)計為varchar(25)
或比25
更大的值,但是,也不要過于夸張,避免影響語義。
使用Mybatis時定義的抽象方法:
使用Mybatis時,定義的抽象方法都必須在接口中,通常,接口會使用Mapper
作為名稱的最后一個單詞,例如命令為BrandMapper
等。
關(guān)于抽象方法的聲明原則:
返回值類型:如果需要執(zhí)行的SQL是增、刪、改類型的,統(tǒng)一使用
int
作為返回值類型,表示“受影響的行數(shù)”,其實也可以使用void
,但并不推薦,如果需要執(zhí)行的SQL是查詢類型的,如果查詢最多只返回1個結(jié)果,則只需要保證返回值類型可以裝得下所需的查詢結(jié)果即可,如果查詢返回的結(jié)果可能超過1條,則必須使用List
集合進(jìn)行封裝,且集合的元素類型依然只需要保證可以裝得下所需的查詢結(jié)果即可方法名稱:自定義
獲取單個對象的方法用 get 做前綴
獲取多個對象的方法用 list 做前綴
獲取統(tǒng)計值的方法用 count 做前綴
插入的方法用 save/insert 做前綴
刪除的方法用 remove/delete 做前綴
修改的方法用 update 做前綴
參數(shù)列表:如果需要執(zhí)行的SQL語句中的參數(shù)數(shù)量較多,推薦將多個參數(shù)封裝到自定義類中
關(guān)于@Mapper和@MapperScan
Mybatis框架只要求開發(fā)人員編寫接口和抽象方法,不需要開發(fā)人員編寫實現(xiàn)類,是因為Mybatis會通過代理模式自動生成接口的實現(xiàn)對象,但是,它需要明確哪些接口是需要生成代理對象的。
可以在各接口上添加@Mapper
注解,在啟動項目時,Mybatis會對整個項目進(jìn)行掃描,對于已經(jīng)添加此注解的接口,就會生成代理對象。
也可以在配置類上添加@MapperScan
注解,用于指定各接口所在的包,則Mybatis會掃描此包及其子孫包下的所有接口,并生成這些接口的代理對象。
關(guān)于@Mapper
和@MapperScan
這2種注解,只需要選擇其中1種使用即可,通常推薦@MapperScan
。
注意:使用@MapperScan
時,一定只指向Mapper接口所在的包,并確保此包下無其它接口!
提示:Mybatis框架的@MapperScan
,與Spring框架的@ComponentScan
沒有任何關(guān)系,且不會互相影響!
使用Mybatis實現(xiàn)插入數(shù)據(jù):
以實現(xiàn)“插入品牌數(shù)據(jù)”為例,需要執(zhí)行的SQL語句大致是:
先在項目的默認(rèn)包下創(chuàng)建pojo.entity.Brand
類,類中的屬性應(yīng)該與數(shù)據(jù)表對應(yīng):
接下來,準(zhǔn)備接口和抽象方法,在項目的默認(rèn)包下創(chuàng)建mapper.BrandMapper
接口,并在接口中添加抽象方法:
關(guān)于SQL語句,可以使用@Insert
等注解進(jìn)行配置,但不推薦!
推薦使用XML文件配置SQL語句,此文件模版可以通過?http://doc.canglaoshi.org/config/Mapper.xml.zip?下載。
然后,在src/main/resources
下創(chuàng)建mapper
文件夾,將下載得到的zip文件解壓,得到SomeMapper.xml
文件,將此XML文件復(fù)制到mapper
文件夾中。
先將SomeMapper.xml
重命名為BrandMapper.xml
。
關(guān)于此文件的配置:
根節(jié)名必須是
<mapper>
根節(jié)點(diǎn)必須配置
namespace
屬性,取值為對應(yīng)的接口的全限定名在根節(jié)點(diǎn)內(nèi)部,根據(jù)需要執(zhí)行的SQL語句的類型不同,使用
<insert>
、<delete>
、<update>
、<select>
節(jié)點(diǎn)在
<insert>
等節(jié)點(diǎn)上,必須配置id
屬性,取值為抽象方法的名稱(不包含括號及參數(shù))在
<insert>
等節(jié)點(diǎn)內(nèi)部,配置SQL語句,SQL語句不需要使用分號結(jié)束
例如配置為:
最后,還需要補(bǔ)充一個配置,用于告訴Mybatis框架這類XML文件的位置!在application.properties
中添加:
另外,在插入數(shù)據(jù)時,還可以配置,得到自動編號的ID值,具體做法是在<insert>
節(jié)點(diǎn)上添加配置:
<!-- int insert(Brand brand); --><insert id="insert" useGeneratedKeys="true" keyProperty="id"> ? ?暫不關(guān)心此處的SQL語句</insert>
使用Mybatis實現(xiàn)批量刪除數(shù)據(jù)
在Mybatis中,有“動態(tài)SQL”的機(jī)制,它允許根據(jù)調(diào)用方法時傳入的參數(shù)值不同,來生成不同的SQL語句。
目標(biāo):根據(jù)若干個id
一次性刪除多個品牌。
需要執(zhí)行的SQL語句大致是:
或者:
注意:以上SQL語句中的id
的數(shù)量是不確定的。
在BrandMapper
接口中,抽象方法可以是:
或者:
或者:
在BrandMapper.xml
中配置SQL語句:
由于需要對參數(shù)ids
(若干個id
)進(jìn)行遍歷,需要使用到動態(tài)SQL中的<foreach>
節(jié)點(diǎn),此節(jié)點(diǎn)可以對數(shù)組或集合進(jìn)行遍歷!關(guān)于<foreach>
的配置:
collection
屬性:表示被遍歷的參數(shù)對象,當(dāng)抽象方法的參數(shù)只有1個,且沒有添加@Param
注解時,當(dāng)參數(shù)值的類型是數(shù)組時,此屬性值為array
,當(dāng)參數(shù)值的類型是List
時,此屬性值為list
;否則,此屬性值為@Param
注解中的參數(shù)值item
屬性:表示被遍歷到的元素的名稱,是自定義的名稱,在<foreach>
內(nèi)部,使用#{}
格式的占位符時,也使用此屬性來表示每個元素separator
屬性:表示遍歷過程中各元素值之間的分隔符號
最后,在BrandMapperTests
中編寫并執(zhí)行測試:
使用Mybatis實現(xiàn)動態(tài)SQL的修改數(shù)據(jù)
在動態(tài)SQL機(jī)制中,可以使用<if>
標(biāo)簽,可用于對某參數(shù)值進(jìn)行判斷,從而生成不同的SQL語句片段,常用于設(shè)計更新數(shù)據(jù)的操作。
目標(biāo):使用1個方法,實現(xiàn)多種不同的數(shù)據(jù)更新(想更新哪些字段就更新哪些字段,不想更新的字段值將保持不變)
需要執(zhí)行的SQL語句大致是:
注意:以上SQL語句的修改的字段列表應(yīng)該不是固定的,應(yīng)該根據(jù)傳入的參數(shù)值來決定。
先在BrandMapper
接口中添加抽象方法:
然后,在BrandMapper.xml
中進(jìn)行配置:
需要注意的是,在Mybatis的動態(tài)SQL中,<if>
并沒有對應(yīng)的<else>
,如果一定要實現(xiàn)類似Java中的if...else
效果,需要使用<choose>
標(biāo)簽,其基本格式是:
或者,也可以使用2個條件完全相反的<if>
標(biāo)簽來實現(xiàn)類似效果(但是執(zhí)行效率偏低),例如:
使用Mybatis實現(xiàn)查詢數(shù)據(jù)
統(tǒng)計查詢
目標(biāo):統(tǒng)計品牌表中的數(shù)據(jù)的數(shù)量
需要執(zhí)行的SQL語句大致是:
在BrandMapper
接口中添加抽象方法:
在BrandMapper.xml
中配置SQL:
注意:所有查詢節(jié)點(diǎn)(<select>
)必須配置resultType
或resultMap
這2個屬性中的其中1個。
當(dāng)使用resultType
聲明封裝結(jié)果的數(shù)據(jù)類型時,取值與抽象方法的返回值對應(yīng),如果是基本類型,直接寫類型名稱即可,例如resultType="int"
,如果是引用數(shù)據(jù)類型,在java.lang
包下的可以直接寫類名,其它包下的寫全限定名。
指定條件的單一結(jié)果查詢:
目標(biāo):根據(jù)id查詢品牌詳情
需要執(zhí)行的SQL語句大致是:
由于不推薦使用星號表示字段列表,并且,在實際查詢時,可能有部分字段是不需要體現(xiàn)在查詢結(jié)果中的,推薦的做法是針對所需的查詢字段,另外創(chuàng)建類型進(jìn)行結(jié)果的封裝。
例如,在pojo.vo
下創(chuàng)建BrandDetailVO
類:
在BrandMapper
接口中添加抽象方法:
然后,在BrandMapper.xml
中配置SQL:
另外,在查詢時,一定要明確幾個概念:
字段(Field):在創(chuàng)建數(shù)據(jù)表時指定的名稱(后續(xù)也能修改表結(jié)構(gòu)時改名)
列(Column):查詢的結(jié)果集中的每一豎排,列名默認(rèn)情況下是字段名,如果查詢時指定了別名,則列名就是指定的別名
屬性( Property):類中的屬性
Mybatis在執(zhí)行查詢時,會嘗試自動的將結(jié)果集中的數(shù)據(jù)封裝到返回結(jié)果類型的對象中,但是,它只能自動處理列名與屬性名相同的部分,如果列名與屬性名不同,默認(rèn)并不能自動封裝!
可以在查詢的SQL語句中,自定義別名,使得列名與屬性名相同,則可以實現(xiàn)自動封裝,例如:
以上的product_count AS productCount
自定義別名可以保證product_count
字段的值可以被自動封裝!
更推薦使用<resultMap>
來指導(dǎo)Mybatis如何封裝結(jié)果,它將與<select>
標(biāo)簽的resultMap
屬性一起使用,例如:
然后,在<resultMap>
內(nèi)部,使用<result>
來配置列名與屬性名的對應(yīng)關(guān)系,例如:
提示:在使用<resultMap>
配置時,從規(guī)范的角度出發(fā),每個列與屬性的關(guān)系都需要顯式的配置出來(即使從功能實現(xiàn)的角度來看可能并不需要),另外,還應(yīng)該使用<id>
節(jié)點(diǎn)對主鍵進(jìn)行配置。
查詢列表
目標(biāo):查詢品牌列表
需要執(zhí)行的SQL語句大致是(暫時使用星號表示字段列表):
通常,查詢列表時,所需要查詢的字段與查單個數(shù)據(jù)可能是不同的,所以,可能需要自定義新的VO類作為List
中的元素類型,為了避免寫完代碼后發(fā)現(xiàn)某個VO不能復(fù)用于查詢單個數(shù)據(jù)和查詢列表這2個功能,推薦一開始就定義用于封裝列表項結(jié)果的VO類,例如:
在BrandMapper
接口中添加抽象方法:
然后,在BrandMapper.xml
中配置SQL:
關(guān)于<sql>
與<resultMap>
在使用XML配置SQL語句時,可以使用<sql>
封裝SQL語句片段,并使用<include>
進(jìn)行引用,例如:
通過,使用<sql>
封裝字段列表,而<resultMap>
通常與之對應(yīng),所以,這2個節(jié)點(diǎn)的id
命名通常會使用相同的關(guān)鍵詞,例如<sql>
配置為id="ListItemQueryFields"
,并且<resultMap id="ListItemResultMap">
,甚至,在編碼時,會把這2個節(jié)點(diǎn)放在相鄰的位置。
提示:使用<sql>
封裝字段列表時,IntelliJ IDEA可能會誤判為錯誤的語法,將字段列表使用<if test="true>"
框?。ɑ?qū)⒋?code><if>添加在之前)即可避免出現(xiàn)這樣的錯誤提示。
關(guān)于異常
BindingException
綁定異常,異常提示信息如下:
出現(xiàn)此異常是因為找不到與抽象方法對應(yīng)的SQL語句,原因可能有:
在XML中配置的接口名有誤
<mapper>
節(jié)點(diǎn)的namespace
屬性值有誤在XML中配置的抽象方法名稱有誤
<insert>
或類似節(jié)點(diǎn)的id
屬性值有誤在配置文件中指定的XML路徑,此項配置有誤
application.properties
中配置的mybatis.mapper-locations
屬性有誤如果十分確實以上代碼都沒有問題,則只可能是依賴項出錯
先檢查
pom.xml
中的依賴代碼是否正確,如果無誤,則刪除本地倉庫并重新下載
關(guān)于#{}
和${}
格式的占位符
提示:在開發(fā)實踐中,并不推薦使用${}
格式的占位符。
假設(shè)需要實現(xiàn):?分頁查詢品牌數(shù)據(jù)。
需要執(zhí)行的SQL語句大致是:
以上SQL語句中,需要使用到2個參數(shù),分別表示“跳過幾條記錄”、“查詢幾條記錄”。
在BrandMapper
中添加抽象方法:
提示:offset表示“偏移量”。
在BrandMapper.xml
中配置SQL:
完成后,在BrandMapperTests
中測試:
經(jīng)過測試,可以發(fā)現(xiàn),在配置SQL時,2個參數(shù)無論使用#{}
還是${}
都可以正常運(yùn)行!
假設(shè)需要實現(xiàn):根據(jù)名稱查詢品牌詳情
在BrandMapper
中添加抽象方法:
在BrandMapper.xml
中配置SQL:
完成后,在BrandMapperTests
中測試:
經(jīng)過測試,可以發(fā)現(xiàn),在配置SQL時,參數(shù)使用#{}
可以正常運(yùn)行,但是使用${}
會出錯!
其實,#{}
和${}
這2種占位符的處理機(jī)制是不同的!
當(dāng)占位符是#{}
時,是預(yù)編譯的,會先將SQL語句中的參數(shù)使用?
表示,當(dāng)編譯通過后,再將參數(shù)值代入并執(zhí)行。
當(dāng)占位符是${}
時,不是預(yù)編譯的,會將各參數(shù)值先拼接到SQL語句中,然后再執(zhí)行編譯流程,完成后,再執(zhí)行SQL語句。
以分頁查詢?yōu)槔?,?dāng)使用#{}
時,其大致SQL是:
以上SQL會先執(zhí)行編譯流程,完成后,再將參數(shù)值代入并執(zhí)行SQL語句。
當(dāng)使用${}
時,需要先將參數(shù)值代入,假設(shè)offset
的值是5
,count
的值是3
,則其SQL大致是:
然后,會將以上SQL語句進(jìn)行編譯流程,最終執(zhí)行SQL語句。
換成根據(jù)名稱來查詢時,當(dāng)#{}
占位符時,其SQL語句大致是:
當(dāng)使用${}
占位符時,依然是先使用參數(shù)值替換占位符,得到的SQL語句大致是:
由于華為
這2個字并沒有添加引號表示這是一個字符串,所以,會被視為字段名,最終執(zhí)行時的錯誤就是:
所以,當(dāng)使用${}
格式的占位符,且參數(shù)值是字符串類型時(其實,其它非數(shù)值型都是如此),需要考慮數(shù)據(jù)類型的問題,例如,以上出錯時,將測試數(shù)據(jù)的華為
改成'華為'
即可。
結(jié)論:使用${}
格式的占位符,需要自行考慮數(shù)據(jù)類型的問題,但是,使用#{}
時,并不需要。
另外,如果不使用預(yù)編譯的做法,由于參數(shù)值可以改變語義,所以,還存在SQL注入的風(fēng)險!
所以,為了保證SQL語句不會被注入,不應(yīng)該使用${}
格式的占位符!
提示:即便${}
格式的占位符是有SQL注入風(fēng)險的,但是,也并不是不能解決的,可以在執(zhí)行SQL語句之前,對參數(shù)值使用正則表達(dá)式檢查,如果存在SQL注入的關(guān)鍵字時,不執(zhí)行SQL語句即可。
Mybatis的緩存機(jī)制
緩存:是一種臨時存儲數(shù)據(jù)的機(jī)制,甚至,使用這種機(jī)制存儲的數(shù)據(jù)也只是臨時使用而已。
通常,使用緩存存儲數(shù)據(jù)時,都會比其它的某種處理機(jī)制更快(訪問數(shù)據(jù)的速度更快,效率更高)!
當(dāng)使用Mybatis實現(xiàn)增刪改查的數(shù)據(jù)訪問時,本質(zhì)上,程序是運(yùn)行在APP服務(wù)器上,而數(shù)據(jù)庫通常都在另一臺服務(wù)器上,則訪問數(shù)據(jù)的效率非常低(需要在2臺電腦之間進(jìn)行互相通信,另外,還可以處理SQL語句、查詢結(jié)果等),特別是查詢數(shù)據(jù)非常多的數(shù)據(jù)表,在沒有索引等機(jī)制的情況下,每次查詢耗時都非常久!
通常,會使用緩存來解決查詢效率低下的問題(與增刪改無關(guān)),Mybatis內(nèi)置的緩存機(jī)制就是將查詢到的結(jié)果臨時存儲到APP服務(wù)器上,下次執(zhí)行相同的查詢時,直接將APP服務(wù)器上的結(jié)果進(jìn)行返回即可,并不會真實的查詢MySQL數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)。'

Mybatis在處理緩存時,區(qū)分為一級緩存和二級緩存(是2種不同的緩存機(jī)制,但可同時存在)。
Mybatis的一級緩存又被稱之為“會話緩存”,是默認(rèn)開啟的,且無法關(guān)閉,其能夠緩存數(shù)據(jù)的條件是:
必須是同一個會話
必須是通過同一個Mapper接口的對象執(zhí)行的查詢
必須是執(zhí)行完全相同的SQL語句
必須是完全相同的SQL參數(shù)
當(dāng)滿足以上條件時,查詢到的每個數(shù)據(jù)都會被Mybatis緩存下來,并且,下次查詢的還是此數(shù)據(jù)時,將直接返回此前緩存的結(jié)果。
一級緩存會在關(guān)閉Session、通過SqlSession清空緩存、通過此會話的Mapper使得表中的數(shù)據(jù)發(fā)生修改時自動清空緩存數(shù)據(jù)!
Mybatis的二級緩存又稱之為"namespace緩存",是作用于每一個XML配置的緩存,也就是說,只要執(zhí)行的是同一個XML中的同一個查詢,且參數(shù)相同,即使使用不同的會話,也可以共用緩存數(shù)據(jù)!
在整合Spring的Mybatis工程中(包括Spring Boot),二級緩存默認(rèn)是全局開啟,但各namespace默認(rèn)未開啟的,如果需要開啟各namespace緩存,需要在XML文件中添加<cache/>
節(jié)點(diǎn)(此節(jié)點(diǎn)直屬于根節(jié)點(diǎn),與其它同級節(jié)點(diǎn)不區(qū)分先后順序)。
注意:二級緩存的數(shù)據(jù)必須在sqlSession
提交(commit
)或關(guān)閉(close
)后才會產(chǎn)生。
注意:Mybatis在執(zhí)行查詢時,會先查找二級緩存,如果命中,直接返回結(jié)果,如果未命中,則查詢一級緩存,如果命中則返回一級緩存中的結(jié)果,如果仍未命中,則執(zhí)行實際的查詢(連接到數(shù)據(jù)庫服務(wù)器查詢數(shù)據(jù))。
提示:使用二級緩存后,輸出中的日志中將包含Cache Hit Ratio
信息,此信息表示的是“緩存數(shù)據(jù)的命中率”,將在日志的尾部通過0.0
、0.5
類似的數(shù)值表示。
另外,在每個查詢的<select>
上還可以配置useCache
屬性,取值為true
?/?false
,表示此查詢是否使用緩存,默認(rèn)值為true
。
另外,當(dāng)開啟二級緩存后,封裝查詢結(jié)果的類型必須實現(xiàn)Serializable
接口,否則就會出現(xiàn)不可序列化的異常!
二級緩存也會因為當(dāng)前namespace中執(zhí)行了增刪改操作而清空緩存數(shù)據(jù)!
【總結(jié)】
Mybatis內(nèi)置的緩存機(jī)制有一級緩存和二級緩存這2種,并且,在執(zhí)行查詢時,會先查找二級緩存,再查找一級緩存。
其中,一級緩存是會話緩存,必須是同一個會話、同一個Mapper、執(zhí)行同樣的SQL、且使用同樣的SQL參數(shù),才會應(yīng)用緩存,且一級緩存會因為關(guān)閉會話、在會話中主動清除緩存、使用此會話的Mapper執(zhí)行了任何寫操作后自動清除緩存數(shù)據(jù),一級緩存是默認(rèn)開啟的,一定程度上人為不可控;二級緩存是Namespace緩存,即使不同的會話也可以使用到緩存數(shù)據(jù),默認(rèn)是全局開啟、各Namespace未開啟的狀態(tài),當(dāng)需要使用Namespace緩存時,需要在XML文件中添加<cache/>
節(jié)點(diǎn)以開啟當(dāng)前Namespace的二級緩存,另外,還可以在各<select>
節(jié)點(diǎn)上配置useCache
屬性,以配置某個查詢功能是否使用二級緩存,并且,使用二級緩存時,需要封裝結(jié)果的類型實現(xiàn)了Serializable
接口,二級緩存也會因為寫數(shù)據(jù)而被清除。
由于無論是一級緩存還是二級緩存,都會因為發(fā)生了數(shù)據(jù)的寫操作后清除緩存數(shù)據(jù),以保證緩存數(shù)據(jù)的準(zhǔn)確性,但是,這種機(jī)制并不一定符合開發(fā)實踐中的應(yīng)用需求,在開發(fā)實踐中,可能并不需要每時每刻關(guān)注每個數(shù)據(jù)的準(zhǔn)確性,例如微博的熱搜、頭條的熱榜的機(jī)制是每10分鐘或15分鐘更新一次緩存數(shù)據(jù),通過Mybatis的緩存機(jī)制是做不到這一點(diǎn)的,所以,通常會使用自定義策略的緩存做法,例如使用Redis來處理緩存。
自動更新gmt_create和gmt_modified的Mybatis攔截器
MybatisConfiguration.java
InsertUpdateTimeInterceptor.java