MyBatis:lazy loading
懶加載的原理
mybatis 會循環處理結果集中返回的每行數據的,在處理之前首先會通過反射調用構造方法來創建 result 對象,結果集中的一行數據最終會映射為一個 result 對象(嚴格的來說是不對的,結果集中的一行數據在多表連接的情況下可能會映射為多個 result 對象,結果集中的一行數據在多表連接一對多的情況下結果集中的多行數據可能映射一個 result 對象,簡單的單表查詢結果集中的一行數據映射為一個 result 對象)。
其實在調用構造方法創建 result 對象的時候,構造方法還可能會有參數,需要先把結果集中的參數都提取出來,傳給相應的構造方法通過反射創建對象。
mybatis 其實第一步是解析配置文件,把配置文件映射為 mybatis 的 Configuration 類,把配置文件的 xml 屬性都映射為 Java 對象中的屬性值。xml mapper 文件的處理比較復雜,< resultMap/> 標簽映射為 ResultMap 對象, 標簽中的< id/> 、< result/>、< association/> 等映射為 ResultMapping 對象。
其實要講 mybatis 的實現過程,涉及到的點太多了,沒法在一篇博客中講。在這里,我只簡單的講一下原理。
接著再講創建好 result 對象之后,mybatis 會循環 resultMappings(標簽中的每個子標簽都映射為一個 resultMapping,這些 resultMapping 組成了一個集合就是 resultMappings)集合,看有沒有需要懶加載的屬性,如果有的話,則會為這個 result 對象創建一個代理對象。
什么情況下才會出現需要懶加載的屬性呢?只有 < association property=”author” column=”author_id” select=”selectAuthor” fetchType=”lazy”/>?
和 < collection property=”xxx” column=”xxx” select=”xxxx” fetchType=”lazy”/> 作為一個子標簽出現在 < resultMap/> 標簽(也不一定只是 < resultMap/> 標簽,< collection/> 等標簽事實上也算是一個 < resultMap/> 標簽)之內才會出現需要懶加載的屬性。select 屬性和 fetchType=”lazy” 必須同時出現在 < collection/> 或 < association/> 屬性中才需要懶加載,select 表示的是嵌套查詢語句的 id ,fetchType=”lazy” 表示的是懶加載。
再接著講 result 對象的代理對象,代理類是由 javassist 框架在運行時創建和加載的,這個代理類繼承自 result 對象所屬的類,以上面的例子為例,這個代理類繼承自 Blog 類。
對于這個代理類的詳細講解在我的博客深入理解 Java 動態代理中有很詳細的介紹,在這里我再簡單的介紹下。
這個代理類繼承了 result 對象所屬的類(被代理類)并重寫了被代理類的所有的方法,所以在代理對象上調用懶加載屬性的 get 方法(getAuthor())時會觸發懶加載動作,mybatis 這時就能發現需要去懶加載一個屬性,然后去加載這個屬性。
其實,有幾個方法都可以觸發懶加載的操作,比如調用懶加載的 get/set 方法(確實調用 set 方法時也會觸發懶加載操作)還有調用 clone()、equals()、hashCode()、toString()方法也會觸發懶加載操作,如果代理對象有多個懶加載屬性,則調用后面的這四個方法時會同時觸發加載所有的懶加載屬性。
懶加載操作只會觸發一次,下次再調用這些方法時不會再次觸發懶加載操作的。
懶加載其實又是一次查詢操作,懶加載查詢需要傳遞一些參數,還有一些其他條件。這些待傳遞的屬性、參數、查詢所需的 sql 語句等相關的條件都已經封裝到了代理對象內部,這些條件封裝在一個 Map 中,鍵是懶加載查詢的屬性名稱,值是查詢該屬性所需的條件,包括參數、sql 語句等。懶加載完一個屬性之后會把這個屬性從 Map 中移除,所以再次出發懶加載操作時 mybatis 就知道該屬性已經被被加載過了,不會重復加載。
懶加載也是一個挺復雜的過程,我在上面的講解中省略了很多,要全部講出來涉及的東西太多。
我再總結一下,懶加載功能使用了代理對象,所以在調用懶加載屬性的 get/set 方法(或者是其他觸發懶加載操作的方法)時 mybatis 才能知道這時候應該去加載懶加載屬性。
?
?
ORM 框架hibernate 也是支持lazy 加載的,相信原理也是類似的。
總結
以上是生活随笔為你收集整理的MyBatis:lazy loading的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下in命令
- 下一篇: 【转】你应该了解的基础和2017测试行业