偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

用了這么久的Mybatis,結(jié)果面試官問(wèn)的問(wèn)題,我竟然還猶豫了

開(kāi)發(fā) 架構(gòu)
Mybatis是一個(gè)半自動(dòng) ORM(對(duì)象關(guān)系映射)框架,它內(nèi)部封裝了JDBC,加載驅(qū)動(dòng)、創(chuàng)建連接、創(chuàng)建 statement 等繁雜的過(guò)程,我們開(kāi)發(fā)的時(shí)候只需要關(guān)注如何編寫(xiě) SQL 語(yǔ)句,而不用關(guān)心其他的。

[[402089]]

本文轉(zhuǎn)載自微信公眾號(hào)「Java極客技術(shù)」,作者鴨血粉絲。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java極客技術(shù)公眾號(hào)。

前段時(shí)間阿粉的一個(gè)朋友和阿粉吃飯,在吃飯的時(shí)候和阿粉瘋狂的吐槽面試官,說(shuō)面試官問(wèn)的問(wèn)題都是些什么問(wèn)題呀,我一個(gè)干了三四年的開(kāi)發(fā),也不說(shuō)問(wèn)點(diǎn)靠譜的,阿粉很好奇,問(wèn)題問(wèn)完基礎(chǔ)的,一般不都是根據(jù)你自己的簡(jiǎn)歷進(jìn)行提問(wèn)么?而接下來(lái)他說(shuō)的出來(lái)的問(wèn)題,阿粉表示,阿粉需要繼續(xù)學(xué)習(xí)了。

Mybatis是什么?

說(shuō)到這個(gè),讀者大人們肯定心想,阿粉是在開(kāi)玩笑么?你一個(gè) Java 程序員,你不知道Mybatis是啥么?不就是個(gè)持久層的框架么,這東西有啥好說(shuō)的呢?但是阿粉還是要給大家說(shuō)。

Mybatis是一個(gè)半自動(dòng) ORM(對(duì)象關(guān)系映射)框架,它內(nèi)部封裝了JDBC,加載驅(qū)動(dòng)、創(chuàng)建連接、創(chuàng)建 statement 等繁雜的過(guò)程,我們開(kāi)發(fā)的時(shí)候只需要關(guān)注如何編寫(xiě) SQL 語(yǔ)句,而不用關(guān)心其他的。

為什么說(shuō) Mybatis 是一個(gè)半自動(dòng) ORM 的框架呢?

ORM,是Object和Relation之間的映射,而Mybatis 在查詢關(guān)聯(lián)對(duì)象或關(guān)聯(lián)集合對(duì)象時(shí),需要手動(dòng)編寫(xiě) sql 來(lái)完成,所以,稱(chēng)之為半自動(dòng) ORM 框架,而Hibernate 屬于全自動(dòng) ORM 映射工具,使用 Hibernate 查詢關(guān)聯(lián)對(duì)象或者關(guān)聯(lián)集合對(duì)象時(shí),可以根據(jù)對(duì)象關(guān)系模型直接獲取,所以它是全自動(dòng)的。

這也是為什么有些面試官在面試初級(jí)程序員的時(shí)候,很喜歡說(shuō),你覺(jué)得 Mybatis , 和 Hibernate 都有什么優(yōu)缺點(diǎn),為啥你們選擇使用的 Mybatis 而不選擇使用 Hibernate 呢?

我們都說(shuō)了 Mybatis是什么了,接下來(lái)肯定需要說(shuō)說(shuō)面試官都問(wèn)了什么問(wèn)題,能讓阿粉的朋友變得非常猶豫。

Mybatis的一級(jí)、二級(jí)緩存是什么你了解么?

Mybatis 的一級(jí)緩存

我們先說(shuō) Mybatis 的一級(jí)緩存,因?yàn)檫@是如果不手動(dòng)配置,他是自己默認(rèn)開(kāi)啟的一級(jí)緩存,一級(jí)緩存只是相對(duì)于同一個(gè) SqlSession 而言,參數(shù)和SQL完全一樣的情況下,我們使用同一個(gè)SqlSession對(duì)象調(diào)用一個(gè)Mapper方法,往往只執(zhí)行一次SQL,因?yàn)槭褂肧elSession第一次查詢后,MyBatis會(huì)將其放在緩存中,以后再查詢的時(shí)候,如果沒(méi)有聲明需要刷新,并且緩存沒(méi)有超時(shí)的情況下,SqlSession都會(huì)取出當(dāng)前緩存的數(shù)據(jù),而不會(huì)再次發(fā)送SQL到數(shù)據(jù)庫(kù)。

當(dāng)我們面試的時(shí)候,說(shuō)完這個(gè),一般情況下,面試官一定會(huì)追問(wèn)下去,畢竟技術(shù)就是要問(wèn)到你的知識(shí)盲區(qū)才會(huì)停止。

那我們就來(lái)畫(huà)個(gè)圖表示一下一級(jí)緩存:

那面試官肯定會(huì)說(shuō),直接從數(shù)據(jù)庫(kù)查不就行了,為啥要一級(jí)緩存呢?

當(dāng)我們使用MyBatis開(kāi)啟一次和數(shù)據(jù)庫(kù)的會(huì)話時(shí), MyBatis 會(huì)創(chuàng)建出一個(gè) SqlSession 對(duì)象表示一次與數(shù)據(jù)庫(kù)之間的信息傳遞,在我們執(zhí)行 SQL 語(yǔ)句的過(guò)程中,們可能會(huì)反復(fù)執(zhí)行完全相同的查詢語(yǔ)句,如果不采取一些措施,我們每一次查詢都會(huì)查詢一次數(shù)據(jù)庫(kù),而如果在極短的時(shí)間內(nèi)做了很多次相同的查詢操作,那么這些查詢返回的結(jié)果很可能相同。

也就是說(shuō),如果我們?cè)诙虝r(shí)間內(nèi),頻繁的去執(zhí)行一條 SQL ,查詢返回的結(jié)果本來(lái)應(yīng)該是改變了,但是我們查詢出來(lái)的時(shí)候,會(huì)出現(xiàn)結(jié)果一致的情況,正是為了解決這種問(wèn)題,也為了減輕數(shù)據(jù)庫(kù)的開(kāi)銷(xiāo),所以 Mybatis 默認(rèn)開(kāi)啟了一級(jí)緩存。

Mybatis 的二級(jí)緩存

Mybatis 的二級(jí)緩存一般如果你不對(duì)他進(jìn)行設(shè)置,他是不會(huì)開(kāi)啟的,而二級(jí)緩存是什么呢?Mybatis 中的二級(jí)緩存實(shí)際上就是 mapper 級(jí)別的緩存,而這時(shí)候肯定會(huì)有人說(shuō),那么不同之間的 Mapper 是同一個(gè)緩存么?

答案是否定的,他不是一個(gè),Mapper 級(jí)別的緩存實(shí)際上就是相同的 Mapper 使用的是一個(gè)二級(jí)緩存,但是在二級(jí)緩存中,又有多個(gè)不同的 SqlSession ,而不同的 Mapper 之間的二級(jí)緩存也就是互相不會(huì)影響的。

就類(lèi)似下面的圖:

這二級(jí)緩存是不是就看起來(lái)有點(diǎn)意思了?

那怎么能夠開(kāi)啟二級(jí)緩存呢?

1.MyBatis 配置文件

  1. <settings> 
  2.  <setting name = "cacheEnabled" value = "true" /> 
  3. </settings> 

2.MyBatis 要求返回的 POJO 必須是可序列化的

3.Mapper 的 xml 配置文件中加入 標(biāo)簽

既然我們想要了解這個(gè)二級(jí)緩存,那么必然,我們還得知道它里面的配置都有哪些含義。

我們先從標(biāo)簽看起,然后從源碼里面看都有哪些配置信息提供給我們使用:

blocking : 直譯就是調(diào)度,而在 Mybatis 中,如果緩存中找不到對(duì)應(yīng)的 key ,是否會(huì)一直 blocking ,直到有對(duì)應(yīng)的數(shù)據(jù)進(jìn)入緩存。

eviction : 緩存回收策略

而緩存回收策略,在源碼中是有直接體現(xiàn)的,那么他們分別都對(duì)應(yīng)了什么形式呢?

  1. typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); 
  2. typeAliasRegistry.registerAlias("FIFO", FifoCache.class); 
  3. typeAliasRegistry.registerAlias("LRU", LruCache.class); 
  4. typeAliasRegistry.registerAlias("SOFT", SoftCache.class); 
  5. typeAliasRegistry.registerAlias("WEAK", WeakCache.class); 
  • PERPETUAL : 選擇 PERPETUAL 來(lái)命名緩存,暗示這是一個(gè)最底層的緩存,數(shù)據(jù)一旦存儲(chǔ)進(jìn)來(lái),永不清除.好像這種緩存不怎么受待見(jiàn)。
  • FIFO : 先進(jìn)先出:按對(duì)象進(jìn)入緩存的順序來(lái)移除它們
  • LRU : 最近最少使用的:移除最長(zhǎng)時(shí)間不被使用的對(duì)象。
  • SOFT : 軟引用:移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象。
  • WEAK : 弱引用:更積極地移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象。

大家雖然看著 PERPETUAL 排在了第一位,但是它可不是默認(rèn)的,在 Mybatis 的緩存策略里面,默認(rèn)的是 LRU 。

PERPETUAL :

源代碼如下:

  1. public class PerpetualCache implements Cache { 
  2.   private final String id; 
  3.   private Map<Object, Object> cache = new HashMap<>(); 
  4.   public PerpetualCache(String id) { 
  5.     this.id = id; 
  6.   } 

恩?看著是不是有點(diǎn)眼熟,它怎么就只是包裝了 HashMap ? 你還別奇怪,他還真的就是使用的 HashMap ,不得不說(shuō),雖然人家是使用的 HashMap ,但是那可是比咱們寫(xiě)的高端多了。

既然使用 HashMap ,那么必然就會(huì)有Key,那么他們的Key是怎么設(shè)計(jì)的?

CacheKey:

  1. public class CacheKey implements Cloneable, Serializable { 
  2.   private static final long serialVersionUID = 1146682552656046210L; 
  3.   public static final CacheKey NULL_CACHE_KEY = new NullCacheKey(); 
  4.   private static final int DEFAULT_MULTIPLYER = 37; 
  5.   private static final int DEFAULT_HASHCODE = 17; 
  6.   private final int multiplier; 
  7.   private int hashcode; //用于表示CacheKey的哈希碼 
  8.   private long checksum; //總和校驗(yàn),當(dāng)出現(xiàn)復(fù)合key的時(shí)候,分布計(jì)算每個(gè)key的哈希碼,然后求總和 
  9.   private int count;//當(dāng)出現(xiàn)復(fù)合key的時(shí)候,計(jì)算key的總個(gè)數(shù) 
  10.   // 8/21/2017 - Sonarlint flags this as needing to be marked transient.  While true if content is not serializable, this is not always true and thus should not be marked transient. 
  11.   private List<Object> updateList;//當(dāng)出現(xiàn)復(fù)合key的時(shí)候,保存每個(gè)key 
  12.    

確實(shí)牛逼,至于內(nèi)部如何初始化,如何進(jìn)行操作,大家有興趣的可以去閱讀一下源碼,導(dǎo)入個(gè)源碼包,打開(kāi)自己看一下。

FIFO: 先進(jìn)先出緩沖淘汰策略

  1. public class FifoCache implements Cache { 
  2.  
  3.   private final Cache delegate; //被裝飾的Cache對(duì)象 
  4.   private final Deque<Object> keyList;//用于記錄key 進(jìn)入緩存的先后順序 
  5.   private int size;//記錄了緩存頁(yè)的上限,超過(guò)該值需要清理緩存(FIFO) 
  6.  
  7.   public FifoCache(Cache delegate) { 
  8.     this.delegate = delegate; 
  9.     this.keyList = new LinkedList<>(); 
  10.     this.size = 1024; 
  11.   } 

在 FIFO 淘汰策略中使用了 Java 中的 Deque,而 Deque 一種常用的數(shù)據(jù)結(jié)構(gòu),可以將隊(duì)列看做是一種特殊的線性表,該結(jié)構(gòu)遵循的先進(jìn)先出原則。Java中,LinkedList實(shí)現(xiàn)了Queue接口,因?yàn)長(zhǎng)inkedList進(jìn)行插入、刪除操作效率較高。

當(dāng)你看完這個(gè)源碼的時(shí)候,是不是就感覺(jué)源碼其實(shí)也沒(méi)有那么難看懂,里面都是我們已經(jīng)掌握好的知識(shí),只不過(guò)中間做了一些操作,進(jìn)行了一些封裝。

LRU : 最近最少使用的緩存策略

而 LUR 算法,阿粉之前都說(shuō)過(guò),如果對(duì)這個(gè)算法感興趣的話,文章地址給大家送上,經(jīng)典的 LRU 算法,你真的了解嗎?

而我們需要看的源碼則是在 Mybatis 中的源碼,

  1. public class LruCache implements Cache { 
  2.  
  3.   private final Cache delegate; 
  4.   private Map<Object, Object> keyMap; 
  5.   private Object eldestKey;//記錄最少被使用的緩存項(xiàng)key 
  6.  
  7.   public LruCache(Cache delegate) { 
  8.     this.delegate = delegate; 
  9.     setSize(1024);//重新設(shè)置緩存的大小,會(huì)重置KeyMap 字段 如果到達(dá)上限 則更新eldestKey 
  10.   } 
  11.     public void putObject(Object key, Object value) { 
  12.       delegate.putObject(key, value); 
  13.       // 刪除最近未使用的key 
  14.       cycleKeyList(key); 
  15.     } 

SOFT: 基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象

在看到基于垃圾回收器的時(shí)候,阿粉就已經(jīng)開(kāi)始興奮了,竟然有GC的事情,那還不趕緊看看,這如此高大上(裝杯)的事情,來(lái)瞅瞅吧!

  1. public class SoftCache implements Cache { 
  2.   //在SoftCache 中,最近使用的一部分緩存項(xiàng)不會(huì)被GC回收,這就是通過(guò)將其value添加到 
  3.   private final Deque<Object> hardLinksToAvoidGarbageCollection; 
  4.   //引用隊(duì)列,用于記錄GC回收的緩存項(xiàng)所對(duì)應(yīng)的SoftEntry對(duì)象 
  5.   private final ReferenceQueue<Object> queueOfGarbageCollectedEntries; 
  6.   //底層被修飾的Cache 對(duì)象 
  7.   private final Cache delegate; 
  8.   //連接的個(gè)數(shù),默認(rèn)是256 
  9.   private int numberOfHardLinks; 
  10.  
  11.   public SoftCache(Cache delegate) { 
  12.     this.delegate = delegate; 
  13.     this.numberOfHardLinks = 256; 
  14.     this.hardLinksToAvoidGarbageCollection = new LinkedList<>(); 
  15.     this.queueOfGarbageCollectedEntries = new ReferenceQueue<>(); 
  16.   } 
  17.    
  18.   public void putObject(Object key, Object value) { 
  19.       // 清除被GC回收的緩存項(xiàng) 
  20.       removeGarbageCollectedItems(); 
  21.       // 向緩存中添加緩存項(xiàng) 
  22.       delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries)); 
  23.     } 
  24.    public Object getObject(Object key) { 
  25.        Object result = null
  26.        // 查找對(duì)應(yīng)的緩存項(xiàng) 
  27.        @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache 
  28.        SoftReference<Object> softReference = (SoftReference<Object>) delegate.getObject(key); 
  29.        if (softReference != null) { 
  30.          result = softReference.get(); 
  31.          // 已經(jīng)被GC 回收 
  32.          if (result == null) { 
  33.            // 從緩存中清除對(duì)應(yīng)的緩存項(xiàng) 
  34.            delegate.removeObject(key); 
  35.          } else { 
  36.            // See #586 (and #335) modifications need more than a read lock  
  37.            synchronized (hardLinksToAvoidGarbageCollection) { 
  38.              hardLinksToAvoidGarbageCollection.addFirst(result); 
  39.              if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { 
  40.                hardLinksToAvoidGarbageCollection.removeLast(); 
  41.              } 
  42.            } 
  43.          } 
  44.        } 
  45.        return result; 
  46.      } 
  47.     public void clear() { 
  48.         synchronized (hardLinksToAvoidGarbageCollection) { 
  49.           // 清理強(qiáng)引用集合 
  50.           hardLinksToAvoidGarbageCollection.clear(); 
  51.         } 
  52.         // 清理被GC回收的緩存項(xiàng) 
  53.         removeGarbageCollectedItems(); 
  54.         delegate.clear(); 
  55.       } 
  56.     //其中指向key的引用是強(qiáng)引用,而指向value的引用是弱引用 
  57.     private static class SoftEntry extends SoftReference<Object> { 
  58.       private final Object key
  59.    
  60.       SoftEntry(Object key, Object value, ReferenceQueue<Object> garbageCollectionQueue) { 
  61.         super(value, garbageCollectionQueue); 
  62.         this.key = key
  63.       } 
  64.     } 

WEAK : 基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象

  1. public class WeakCache implements Cache { 
  2.   private final Deque<Object> hardLinksToAvoidGarbageCollection; 
  3.   private final ReferenceQueue<Object> queueOfGarbageCollectedEntries; 
  4.   private final Cache delegate; 
  5.   private int numberOfHardLinks; 
  6.  
  7.   public WeakCache(Cache delegate) { 
  8.     this.delegate = delegate; 
  9.     this.numberOfHardLinks = 256; 
  10.     this.hardLinksToAvoidGarbageCollection = new LinkedList<>(); 
  11.     this.queueOfGarbageCollectedEntries = new ReferenceQueue<>(); 
  12.   } 

WeakCache在實(shí)現(xiàn)上與SoftCache幾乎相同,只是把引用對(duì)象由SoftReference軟引用換成了WeakReference弱引用。 

在這里阿粉也就不再多說(shuō)了,關(guān)于 Mybatis 的二級(jí)緩存,你了解了么?下次遇到面試官問(wèn)這個(gè)的時(shí)候,你應(yīng)該知道怎么成功(裝杯)不被打了吧。

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2020-12-01 10:18:16

RabbitMQ

2022-02-08 13:39:35

LinuxUNIX系統(tǒng)

2022-11-04 08:47:52

底層算法數(shù)據(jù)

2021-05-28 06:16:28

藍(lán)牙Wi-FiNFC

2021-07-21 10:10:14

require前端代碼

2021-11-08 10:00:19

require前端模塊

2022-01-25 12:41:31

ChromeResponse接口

2021-05-27 21:18:56

谷歌Fuchsia OS操作系統(tǒng)

2018-01-31 10:24:45

熱插拔原理服務(wù)器

2020-03-30 09:22:03

AI語(yǔ)音技術(shù)機(jī)器視覺(jué)

2025-03-07 02:00:00

webpackPlugin開(kāi)發(fā)

2022-08-28 20:35:52

三次握手四次揮手TCP

2020-12-07 11:05:21

HttpClient代碼Java

2019-10-21 09:56:37

MySQLCOUNTInnoDB

2021-04-28 11:35:06

Java框架日志

2020-09-17 17:53:12

面試ArrayList數(shù)組

2021-11-08 09:18:01

CAS面試場(chǎng)景

2010-08-23 15:06:52

發(fā)問(wèn)

2021-12-25 22:31:10

MarkWord面試synchronize

2020-06-05 18:32:41

HBaseQAQHDFS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)