解析Mybatis延遲加載問(wèn)題
延遲加載問(wèn)題
MyBatis針對(duì)關(guān)聯(lián)表中的數(shù)據(jù)支持延遲加載。延遲加載其實(shí)就是將數(shù)據(jù)加載時(shí)機(jī)推遲,比如推遲嵌套查詢的執(zhí)行時(shí)機(jī)。
延遲加載可以實(shí)現(xiàn)先查詢主表,按需實(shí)時(shí)做關(guān)聯(lián)查詢,返回關(guān)聯(lián)表結(jié)果集,一定程度上提高了效率。
<settings>
<!-- 啟用延遲加載特性,不配置默認(rèn)關(guān)閉該特性-->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 按需加載: false:使用關(guān)聯(lián)屬性時(shí)才進(jìn)行加載; true加載對(duì)象,則加載所有屬性 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
lazyLoadingEnabled:是否啟用延遲加載,默認(rèn)值為false,不啟用延遲加載。lazyLoadingEnabled屬性控制全局是否使用延遲加載,特殊關(guān)聯(lián)關(guān)系也可以通過(guò)嵌套查詢中fetchType屬性單獨(dú)配置(fetchType屬性值可以是lazy或者eager)
aggressiveLazyLoading:是否按需加載屬性,默認(rèn)值false,lazyLoadingEnabled屬性啟用時(shí)只要加載對(duì)象,就會(huì)加載該對(duì)象的所有屬性;關(guān)閉該屬性則會(huì)按需加載,即使用到某關(guān)聯(lián)屬性時(shí),實(shí)時(shí)執(zhí)行嵌套查詢加載該屬性
對(duì)一
<resultMap id="ExtResultMap" type="com.yan.entity.User" extends="BaseResultMap">
<association property="role" select="com.yan.dao.RoleMapper.selectByPrimaryKey" column="role_id"/>
</resultMap>
如果不訪問(wèn)role屬性,則不會(huì)執(zhí)行t_roles表的查詢。當(dāng)訪問(wèn)role屬性時(shí)才會(huì)執(zhí)行查詢操作,而且如果session關(guān)閉,則自動(dòng)新打開(kāi)session執(zhí)行查詢
對(duì)多
<resultMap id="ExtResultMap" type="com.yan.entity.Role" extends="BaseResultMap">
<collection property="users" ofType="com.yan.entity.User" column="id" select="com.yan.dao.UserMapper.selectByRoleId"/>
</resultMap>
緩存
MyBatis支持一二級(jí)緩存
Mybatis提供查詢緩存,如果緩存中有數(shù)據(jù)就不用從數(shù)據(jù)庫(kù)中獲取,用于減輕數(shù)據(jù)壓力,提高系統(tǒng)性能
緩存的重要性是不言而喻的。 使用緩存可以避免頻繁的與數(shù)據(jù)庫(kù)進(jìn)行交互, 尤其是在查詢?cè)蕉唷⒕彺婷新试礁叩那闆r下, 使用緩存對(duì)性能的提高更明顯。
mybatis也提供了對(duì)緩存的支持, 分為一級(jí)緩存和二級(jí)緩存。 但是在默認(rèn)的情況下, 只開(kāi)啟一級(jí)緩存(一級(jí)緩存是對(duì)同一個(gè) SqlSession 而言的)
- 默認(rèn)情況下,只有一級(jí)緩存(SqlSession級(jí)別的緩存,也稱(chēng)為本地緩存)開(kāi)啟
- 二級(jí)緩存需要手動(dòng)開(kāi)啟和配置,是基于namespace級(jí)別的緩存
- 為了提高擴(kuò)展性。MyBatis定義了緩存接口Cache??梢酝ㄟ^(guò)實(shí)現(xiàn)Cache接口來(lái)自定義二級(jí)緩存
- 一級(jí)緩存是SqlSession級(jí)別的緩存。在操作數(shù)據(jù)庫(kù)時(shí)需要構(gòu)造sqlSession對(duì)象,在對(duì)象中有一個(gè)數(shù)據(jù)結(jié)構(gòu)HashMap用于存儲(chǔ)緩存數(shù)據(jù)。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域HashMap是互相不影響的
- 二級(jí)緩存是mapper級(jí)別的緩存,多個(gè)SqlSession去操作同一個(gè)Mapper的sql語(yǔ)句,多個(gè)SqlSession可以共用二級(jí)緩存,二級(jí)緩存是跨SqlSession的
一級(jí)緩存
一級(jí)緩存即local cache本地緩存,作用域默認(rèn)為sqlSession。當(dāng)Session flush或close后該Session中的所有Cache將被清空
RoleMapper rm= MybatisSessionFactory.getMapper(RoleMapper.class);
Role role=rm.selectByPrimaryKey(1L);
System.out.println(role.getId()+":"+role.getName());
System.out.println("--------------------------------");
MybatisSessionFactory.closeSession();
rm= MybatisSessionFactory.getMapper(RoleMapper.class);
role=rm.selectByPrimaryKey(1L);
System.out.println(role.getId()+":"+role.getName());
兩次查詢操作,分別是2次sql語(yǔ)句,證明緩存是session級(jí)的。如果不關(guān)閉session,即使2次獲取Mapper執(zhí)行的查詢?nèi)耘f只有一個(gè)sql語(yǔ)句
每個(gè)SqlSession中持有了Executor,每個(gè)Executor中有一個(gè)LocalCache。當(dāng)用戶發(fā)起查詢時(shí),MyBatis根據(jù)當(dāng)前執(zhí)行的語(yǔ)句生成MappedStatement,在Local Cache進(jìn)行查詢,如果緩存命中的話,直接返回結(jié)果給用戶,如果緩存沒(méi)有命中的話,查詢數(shù)據(jù)庫(kù),結(jié)果寫(xiě)入Local Cache,最后返回結(jié)果給用戶
一級(jí)緩存配置
開(kāi)發(fā)者只需在MyBatis的配置文件localCacheScope中可以設(shè)置使用一級(jí)緩存。共有兩個(gè)選項(xiàng)SESSION或者STATEMENT,默認(rèn)是SESSION級(jí)別,即在一個(gè)MyBatis會(huì)話中執(zhí)行的所有語(yǔ)句,都會(huì)共享這一個(gè)緩存。一種是STATEMENT級(jí)別,可以理解為緩存只對(duì)當(dāng)前執(zhí)行的這一個(gè)Statement有效。
UserMapper userMapper = MyBatisSessionFactory.getMapper(UserMapper.class); User user1=userMapper.loadById(1L); System.out.println(user1); SqlSession session = MyBatisSessionFactory.openSession(); session.clearCache();//清空緩存 ,后續(xù)查詢會(huì)發(fā)送SQL語(yǔ)句 User user2=userMapper.loadById(1L); System.out.println(user2); System.out.println(user1==user2); MyBatisSessionFactory.closeSession();
1、第一次發(fā)起查詢用戶id為1的用戶信息,先去找緩存中是否有id為1的用戶信息,如果沒(méi)有,從數(shù)據(jù)庫(kù)查詢用戶信息。得到用戶信息,將用戶信息存儲(chǔ)到一級(jí)緩存中。
2、如果中間sqlSession去執(zhí)行commit操作(執(zhí)行插入、更新、刪除),則會(huì)清空SqlSession中的一級(jí)緩存,這樣做的目的為了讓緩存中存儲(chǔ)的是最新的信息,避免臟讀。
3、第二次發(fā)起查詢用戶id為1的用戶信息,先去找緩存中是否有id為1的用戶信息,緩存中有,直接從緩存中獲取用戶信息。
##源碼分析
SqlSession對(duì)外提供了用戶和數(shù)據(jù)庫(kù)之間交互需要的所有方法,隱藏了底層的細(xì)節(jié)。默認(rèn)實(shí)現(xiàn)類(lèi)是DefaultSqlSession
Executor: SqlSession向用戶提供操作數(shù)據(jù)庫(kù)的方法,但和數(shù)據(jù)庫(kù)操作有關(guān)的職責(zé)都會(huì)委托給Executor。
BaseExecutor是一個(gè)實(shí)現(xiàn)了Executor接口的抽象類(lèi),定義若干抽象方法,在執(zhí)行的時(shí)候,把具體的操作委托給子類(lèi)進(jìn)行執(zhí)行。
Cache: MyBatis中的Cache接口,提供了和緩存相關(guān)的最基本的操作
BaseExecutor成員變量之一的PerpetualCache,是對(duì)Cache接口最基本的實(shí)現(xiàn),其實(shí)現(xiàn)非常簡(jiǎn)單,內(nèi)部持有HashMap,對(duì)一級(jí)緩存的操作實(shí)則是對(duì)HashMap的操作。
1、為執(zhí)行和數(shù)據(jù)庫(kù)的交互,首先需要初始化SqlSession,通過(guò)DefaultSqlSessionFactory開(kāi)啟SqlSession
2、在初始化SqlSesion時(shí),會(huì)使用Configuration類(lèi)創(chuàng)建一個(gè)全新的Executor,作為DefaultSqlSession構(gòu)造函數(shù)的參數(shù)
3、SqlSession創(chuàng)建完畢后,根據(jù)Statment的不同類(lèi)型,會(huì)進(jìn)入SqlSession的不同方法中,如果是Select語(yǔ)句的話,最后會(huì)執(zhí)行到SqlSession的selectList
4、SqlSession把具體的查詢職責(zé)委托給了Executor。如果只開(kāi)啟了一級(jí)緩存的話,首先會(huì)進(jìn)入BaseExecutor的query方法。
5、會(huì)先根據(jù)傳入的參數(shù)生成CacheKey,默認(rèn)將MappedStatement的Id、sql的offset、Sql的limit、Sql本身以及Sql中的參數(shù)傳入了CacheKey這個(gè)類(lèi),最終構(gòu)成CacheKey
6、如果查不到的話,就從數(shù)據(jù)庫(kù)查,在queryFromDatabase中,會(huì)對(duì)localcache進(jìn)行寫(xiě)入。 在query方法執(zhí)行的最后,會(huì)判斷一級(jí)緩存級(jí)別是否是STATEMENT級(jí)別,如果是的話,就清空緩存,這也就是STATEMENT級(jí)別的一級(jí)緩存無(wú)法共享localCache的原因。
##總結(jié)
MyBatis一級(jí)緩存的生命周期和SqlSession一致。MyBatis一級(jí)緩存內(nèi)部設(shè)計(jì)簡(jiǎn)單,只是一個(gè)沒(méi)有容量限定的HashMap,在緩存的功能性上有所欠缺。MyBatis的一級(jí)緩存最大范圍是SqlSession內(nèi)部,有多個(gè)SqlSession或者分布式的環(huán)境下,數(shù)據(jù)庫(kù)寫(xiě)操作會(huì)引起臟數(shù)據(jù),建議設(shè)定緩存級(jí)別為Statement。
##一級(jí)緩存的生命周期
MyBatis在開(kāi)啟一個(gè)數(shù)據(jù)庫(kù)會(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ì)象也一并釋放掉。如果SqlSession調(diào)用了close()方法,會(huì)釋放掉一級(jí)緩存PerpetualCache對(duì)象,一級(jí)緩存將不可用;如果SqlSession調(diào)用了clearCache(),會(huì)清空PerpetualCache對(duì)象中的數(shù)據(jù),但是該對(duì)象仍可使用;SqlSession中執(zhí)行了任何一個(gè)update操作(update()、delete()、insert()) ,都會(huì)清空PerpetualCache對(duì)象的數(shù)據(jù),但是該對(duì)象可以繼續(xù)使用
##一級(jí)緩存的不足
使用一級(jí)緩存的時(shí)候,因?yàn)榫彺娌荒芸鐣?huì)話共享,不同的會(huì)話之間對(duì)于相同的數(shù)據(jù)可能有不一樣的緩存。在有多個(gè)會(huì)話或者分布式環(huán)境下,會(huì)存在臟數(shù)據(jù)的問(wèn)題。如果要解決這個(gè)問(wèn)題,就要用到二級(jí)緩存。
MyBatis 一級(jí)緩存(MyBaits 稱(chēng)其為 Local Cache)無(wú)法關(guān)閉,但是有兩種級(jí)別可選:
session級(jí)別的緩存,在同一個(gè) sqlSession 內(nèi),對(duì)同樣的查詢將不再查詢數(shù)據(jù)庫(kù),直接從緩存中。
statement級(jí)別的緩存,session級(jí)別緩存不能獲取最新數(shù)據(jù): 為了避免這個(gè)問(wèn)題,可以將一級(jí)緩存的級(jí)別設(shè)為 statement 級(jí)別的,這樣每次查詢結(jié)束都會(huì)清掉一級(jí)緩存。
由于不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域不共享,如果使用多個(gè)SqlSession對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作時(shí),就會(huì)出現(xiàn)臟數(shù)據(jù)
##二級(jí)緩存
一級(jí)緩存中,其最大的共享范圍就是一個(gè)SqlSession內(nèi)部,如果多個(gè)SqlSession之間需要共享緩存,則需要使用到二級(jí)緩存。開(kāi)啟二級(jí)緩存后,會(huì)使用CachingExecutor裝飾Executor,進(jìn)入一級(jí)緩存的查詢流程前,先在CachingExecutor進(jìn)行二級(jí)緩存的查詢
二級(jí)緩存開(kāi)啟后,同一個(gè)namespace下的所有操作語(yǔ)句,都影響著同一個(gè)Cache,即二級(jí)緩存被多個(gè)SqlSession共享,是一個(gè)全局的變量。 當(dāng)開(kāi)啟緩存后,數(shù)據(jù)的查詢執(zhí)行的流程就是 二級(jí)緩存 -> 一級(jí)緩存 -> 數(shù)據(jù)庫(kù)。
二級(jí)緩存(全局緩存):基于namespace級(jí)別的緩存,一個(gè)namespace對(duì)應(yīng)一個(gè)二級(jí)緩存
###二級(jí)緩存配置
1、在MyBatis的配置文件中開(kāi)啟二級(jí)緩存。
cacheEnabled 全局性地開(kāi)啟或關(guān)閉所有映射器配置文件中已配置的任何緩存。
2、在MyBatis的映射XML中配置cache或者 cache-ref
- type:cache使用的類(lèi)型,默認(rèn)是PerpetualCache,這在一級(jí)緩存中提到過(guò)。
- eviction: 定義回收的策略,常見(jiàn)的有FIFO,LRU。
- flushInterval: 配置一定時(shí)間自動(dòng)刷新緩存,單位是毫秒。
- size: 最多緩存對(duì)象的個(gè)數(shù)。
- readOnly: 是否只讀,若配置可讀寫(xiě),則需要對(duì)應(yīng)的實(shí)體類(lèi)能夠序列化。
- blocking: 若緩存中找不到對(duì)應(yīng)的key,是否會(huì)一直blocking,直到有對(duì)應(yīng)的數(shù)據(jù)進(jìn)入緩存。
<mapper namespace="com.yan.dao.RoleMapper"> <cache/>
cache-ref代表引用別的命名空間的Cache配置,兩個(gè)命名空間的操作使用的是同一個(gè)Cache。
二級(jí)緩存實(shí)驗(yàn)
1、測(cè)試二級(jí)緩存效果,不提交事務(wù),sqlSession1查詢完數(shù)據(jù)后,sqlSession2相同的查詢是否會(huì)從緩存中獲取數(shù)據(jù)。 可以看到,當(dāng)sqlsession沒(méi)有調(diào)用commit()方法時(shí),二級(jí)緩存并沒(méi)有起到作用。
SqlSession session1=MybatisSessionFactory.getFactory().openSession();
SqlSession session2=MybatisSessionFactory.getSession();
RoleMapper rm1=session1.getMapper(RoleMapper.class);
RoleMapper rm2=session2.getMapper(RoleMapper.class);
Role r1=rm1.selectByPrimaryKey(1L);
session1.commit(); //如果不進(jìn)行提交,則緩存無(wú)效
Role r2=rm2.selectByPrimaryKey(1L);
System.out.println(r1==r2); //不是同一個(gè)對(duì)象,應(yīng)該是對(duì)象的深克隆
2、測(cè)試二級(jí)緩存效果,當(dāng)提交事務(wù)時(shí),sqlSession1查詢完數(shù)據(jù)后,sqlSession2相同的查詢是否會(huì)從緩存中獲取數(shù)據(jù)。 sqlsession2的查詢,使用了緩存,緩存的命中率是0.5。
3、測(cè)試update操作是否會(huì)刷新該namespace下的二級(jí)緩存。 可以看到,在sqlSession3更新數(shù)據(jù)庫(kù),并提交事務(wù)后,sqlsession2的StudentMapper namespace下的查詢走了數(shù)據(jù)庫(kù),沒(méi)有走Cache。
4、驗(yàn)證MyBatis的二級(jí)緩存不適應(yīng)用于映射文件中存在多表查詢的情況。 通常我們會(huì)為每個(gè)單表創(chuàng)建單獨(dú)的映射文件,由于MyBatis的二級(jí)緩存是基于namespace的,多表查詢語(yǔ)句所在的namspace無(wú)法感應(yīng)到其他namespace中的語(yǔ)句對(duì)多表查詢中涉及的表進(jìn)行的修改,引發(fā)臟數(shù)據(jù)問(wèn)題。
5、為了解決實(shí)驗(yàn)4的問(wèn)題呢,可以使用Cache ref,讓ClassMapper引用StudenMapper命名空間,這樣兩個(gè)映射文件對(duì)應(yīng)的Sql操作都使用的是同一塊緩存了。 不過(guò)這樣做的后果是,緩存的粒度變粗了,多個(gè)Mapper namespace下的所有操作都會(huì)對(duì)緩存使用造成影響。
<mapper namespace="com.yan.dao.UserMapper"> <cache-ref namespace="com.yan.dao.RoleMapper"/>
###二級(jí)緩存源碼
在一級(jí)緩存處理前,用CachingExecutor裝飾了BaseExecutor的子類(lèi),在委托具體職責(zé)給delegate之前,實(shí)現(xiàn)了二級(jí)緩存的查詢和寫(xiě)入功能
CachingExecutor的query方法,首先會(huì)從MappedStatement中獲得在配置初始化時(shí)賦予的Cache。
本質(zhì)上是裝飾器模式的使用,具體的裝飾鏈?zhǔn)荢ynchronizedCache -> LoggingCache -> SerializedCache -> LruCache -> PerpetualCache。
- SynchronizedCache: 同步Cache,實(shí)現(xiàn)比較簡(jiǎn)單,直接使用synchronized修飾方法。
- LoggingCache: 日志功能,裝飾類(lèi),用于記錄緩存的命中率,如果開(kāi)啟了DEBUG模式,則會(huì)輸出命中率日志。SerializedCache: 序列化功能,將值序列化后存到緩存中。該功能用于緩存返回一份實(shí)例的Copy,用于保存線程安全。LruCache: 采用了Lru算法的Cache實(shí)現(xiàn),移除最近最少使用的key/value。
- PerpetualCache: 作為為最基礎(chǔ)的緩存類(lèi),底層實(shí)現(xiàn)比較簡(jiǎn)單,直接使用了HashMap。
總結(jié)
- MyBatis的二級(jí)緩存相對(duì)于一級(jí)緩存來(lái)說(shuō),實(shí)現(xiàn)了SqlSession之間緩存數(shù)據(jù)的共享,同時(shí)粒度更加的細(xì),能夠到namespace級(jí)別,通過(guò)Cache接口實(shí)現(xiàn)類(lèi)不同的組合,對(duì)Cache的可控性也更強(qiáng)。
- MyBatis在多表查詢時(shí),極大可能會(huì)出現(xiàn)臟數(shù)據(jù),有設(shè)計(jì)上的缺陷,安全使用二級(jí)緩存的條件比較苛刻。一般在具體開(kāi)發(fā)中不使用MyBatis的二級(jí)緩存,而是通過(guò)Spring框架引入業(yè)務(wù)層緩存
- 在分布式環(huán)境下,由于默認(rèn)的MyBatis Cache實(shí)現(xiàn)都是基于本地的,分布式環(huán)境下必然會(huì)出現(xiàn)讀取到臟數(shù)據(jù),需要使用集中式緩存將MyBatis的Cache接口實(shí)現(xiàn),有一定的開(kāi)發(fā)成本,直接使用Redis,Memcached等分布式緩存可能成本更低,安全性也更高。
到此這篇關(guān)于Mybatis的延遲加載問(wèn)題的文章就介紹到這了,更多相關(guān)Mybatis延遲加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MyBatis高級(jí)映射學(xué)習(xí)教程
- MyBatis高級(jí)映射和查詢緩存
- Mybatis高級(jí)映射、動(dòng)態(tài)SQL及獲得自增主鍵的解析
- mybatis高級(jí)映射一對(duì)多查詢實(shí)現(xiàn)代碼
- 基于mybatis高級(jí)映射多對(duì)多查詢的實(shí)現(xiàn)
- javaMybatis映射屬性,高級(jí)映射詳解
- MyBatis延遲加載與立即加載案例教程
- MyBatis高級(jí)映射ResultMap解決屬性問(wèn)題
- Mybatis中的延遲加載,以及原理分析
- MyBatis實(shí)現(xiàn)高級(jí)映射的示例代碼
- 詳解MyBatis延遲加載是如何實(shí)現(xiàn)的
- MyBatis高級(jí)映射及延遲加載的實(shí)現(xiàn)
相關(guān)文章
ElasticSearch不停機(jī)重建索引延伸思考及優(yōu)化詳解
這篇文章主要為大家介紹了ElasticSearch不停機(jī)重建索引延伸思考及優(yōu)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
java hibernate使用注解來(lái)定義聯(lián)合主鍵
這篇文章主要介紹了java hibernate使用注解來(lái)定義聯(lián)合主鍵的相關(guān)資料,需要的朋友可以參考下2017-01-01
利用Java實(shí)現(xiàn)更改Word中的頁(yè)面大小和頁(yè)面方向
這篇文章主要為大家詳細(xì)介紹了一種高效便捷的方法——通過(guò)Java應(yīng)用程序,以編程方式更改Word中的頁(yè)面大小和頁(yè)面方向,感興趣的可以了解一下2023-03-03
Java Web項(xiàng)目部署在Tomcat運(yùn)行出錯(cuò)與解決方法示例
這篇文章主要介紹了Java Web項(xiàng)目部署在Tomcat運(yùn)行出錯(cuò)與解決方法,結(jié)合具體實(shí)例形式分析了Java Web項(xiàng)目部署在Tomcat過(guò)程中由于xml配置文件導(dǎo)致的錯(cuò)誤問(wèn)題常見(jiàn)提示與解決方法,需要的朋友可以參考下2017-03-03
springboot斷言異常封裝與統(tǒng)一異常處理實(shí)現(xiàn)代碼
異常處理其實(shí)一直都是項(xiàng)目開(kāi)發(fā)中的大頭,但關(guān)注異常處理的人一直都特別少,下面這篇文章主要給大家介紹了關(guān)于springboot斷言異常封裝與統(tǒng)一異常處理的相關(guān)資料,需要的朋友可以參考下2023-01-01
Spring Boot整合Swagger測(cè)試api構(gòu)建全紀(jì)錄
這篇文章主要給大家介紹了關(guān)于Spring Boot整合Swagger測(cè)試api構(gòu)建的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01
Java簡(jiǎn)單數(shù)據(jù)加密方法DES實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Java簡(jiǎn)單數(shù)據(jù)加密方法DES實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
SpringBoot集成Druid監(jiān)控頁(yè)面最小化配置操作
這篇文章主要介紹了SpringBoot集成Druid監(jiān)控頁(yè)面最小化配置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09

