1. 程式人生 > >mybatis association 懶載入實現原理

mybatis association 懶載入實現原理

前言

mybatis的association 標籤可以設定關聯物件,載入方式;如下的user關聯dept,載入方式fetchType=”eager”

 <resultMap id="BaseResultMap" type="testmaven.entity.User">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="dept_id" jdbcType="INTEGER" property="deptId" />
    <association property
="dept" column="dept_id" fetchType="eager" select="testmaven.mapper.DeptMapper.selectByPrimaryKey" >
</association> </resultMap>

以上的配置、意義咱們都知道。但是這裡有兩個問題,第一,主資料以什麼方式獲取的關聯物件,是兩個表關聯查詢的還是獲取主資料後一條一條的查詢的從資料,如果是這樣那麼就會存在N+1的問題?再就是,懶載入時,只有用到主資料時,才會查詢關聯資料,那麼這個“用到”是什麼意思?

關聯資料獲取的原理

association資料的獲取,都是先獲取主資料,然後根據主資料的某些欄位獲取關聯資料,是一條條查詢的,並不是多表關聯查詢的,這種方式存在查詢N+1問題

,具體到載入方式又有些不同

eager

query主資料時,會立刻query關聯資料,這兩個query使用的同一個jdbc connection。

lazy

query主資料庫時,不會query關聯資料,只有在呼叫主資料的方法時,才會query獲取資料(比如例中user.toString()、user.getName()等方法),這兩個query使用不同connection

到這裡,第一個問題,解決了,繼續往下看。

懶載入的實現原理

經過debug發現,在執行主資料的方法時(user.toString()、user.getName()),才會獲取資料。mybatis怎麼實現的?原來mapper返回的類是代理類,mybatis使用javassist技術建立代理類,然後代理類任何方法都會呼叫JavassistProxyFactory$EnhancedResultObjectProxyImpl

的invoke方法,在invoke方法中獲取關聯資料,從而實現了懶載入!

圖1
這裡寫圖片描述

圖2
這裡寫圖片描述

圖3
這裡寫圖片描述

更深層次的研究,打算將代理類輸出到磁碟,反編譯檢視它的原始碼,這部分在研究javassist後再來補充。