mybatis-一对一的关联查询有两种配置方式
1、嵌套結果:
(mybatis-standalone - MyBatisTest - testSelectBlogWithAuthorResult ())
<!-- 根據文章查詢作者,一對一查詢的結果,嵌套查詢--> <resultMap id="BlogWithAuthorResultMap"type="com.leon.domain.associate.BlogAndAuthor"><id column="bid" property="bid" jdbcType="INTEGER"/><result column="name" property="name" jdbcType="VARCHAR"/><!-- 聯合查詢,將author 的屬性映射到ResultMap --><association property="author" javaType="com.leon.domain.Author"><id column="author_id" property="authorId"/><result column="author_name" property="authorName"/></association> </resultMap>2、嵌套查詢:
(mybatis-standalone - MyBatisTest - testSelectBlogWithAuthorQuery ())
<!-- 另一種聯合查詢(一對一)的實現,但是這種方式有“N+1”的問題--> <resultMap id="BlogWithAuthorQueryMap" type="com.leon.domain.associate.BlogAndAuthor"><id column="bid" property="bid" jdbcType="INTEGER"/><result column="name" property="name" jdbcType="VARCHAR"/><association property="author" javaType="com.leon.domain.Author"column="author_id" select="selectAuthor"/> <!-- selectAuthor 定義在下面--> </resultMap> <!-- 嵌套查詢--> <select id="selectAuthor" parameterType="int" resultType="com.leon.domain.Author">select author_id authorId, author_name authorNamefrom author where author_id = #{authorId} </select>其中第二種方式:嵌套查詢,由于是分兩次查詢,當我們查詢了員工信息之后,會再發送一條SQL 到數據庫查詢部門信息。
我們只執行了一次查詢員工信息的SQL(所謂的1),如果返回了N 條記錄,就會再發送N 條到數據庫查詢部門信息(所謂的N),這個就是我們所說的N+1 的問題。這樣會白白地浪費我們的應用和數據庫的性能。
如果我們用了嵌套查詢的方式,怎么解決這個問題?能不能等到使用部門信息的時候再去查詢?這個就是我們所說的延遲加載,或者叫懶加載。
在MyBatis 里面可以通過開啟延遲加載的開關來解決這個問題。
在settings 標簽里面可以配置:
<!--延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。默認false --> <setting name="lazyLoadingEnabled" value="true"/> <!--當開啟時,任何方法的調用都會加載該對象的所有屬性。默認false,可通過select 標簽的 fetchType 來覆蓋--> <setting name="aggressiveLazyLoading" value="false"/> <!-- Mybatis 創建具有延遲加載能力的對象所用到的代理工具,默認JAVASSIST --> <setting name="proxyFactory" value="CGLIB" />lazyLoadingEnabled 決定了是否延遲加載。
aggressiveLazyLoading 決定了是不是對象的所有方法都會觸發查詢。
先來測試一下(也可以改成查詢列表):
1、沒有開啟延遲加載的開關,會連續發送兩次查詢;
2 、開啟了延遲加載的開關, 調用blog.getAuthor() 以及默認的(equals,clone,hashCode,toString)時才會發起第二次查詢,其他方法并不會觸發查詢,比如blog.getName();
3、如果開啟了aggressiveLazyLoading=true,其他方法也會觸發查詢,比如blog.getName()。
問題:為什么可以做到延遲加載?blog.getAuthor(),只是一個獲取屬性的方法,里面并沒有連接數據庫的代碼,為什么會觸發對數據庫的查詢呢?
我懷疑:blog 根本不是Blog 對象,而是被人動過了手腳!
把這個對象打印出來看看:
System.out.println(blog.getClass());
果然不對:
class com.leon.domain.associate.BlogAndAuthor_$$_jvst70_0這個類的名字后面有jvst,是JAVASSIST 的縮寫。原來到這里帶延遲加載功能的對象blog 已經變成了一個代理對象,那到底什么時候變成代理對象的?我們后面在看源碼的時候再去分析,這個也先留一個作業給大家。
?
總結
以上是生活随笔為你收集整理的mybatis-一对一的关联查询有两种配置方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis-嵌套(关联)查询/ N+
- 下一篇: 当开启了延迟加载的开关,对象是怎么变成代