Mybatis 的嵌套查詢與嵌套結果的區別


什么是嵌套查詢和嵌套結果

嵌套查詢 是指通過執行另外一條 SQL 映射語句來返回預期的復雜類型;

嵌套結果 是使用嵌套結果映射來處理重復的聯合結果的子集。

開發人員可以使用上述任意一種方式實現對關聯關系的加載。

區別

嵌套查詢 嵌套結果
嵌套查詢是在查詢 SQL 后再進行一個(子)查詢 嵌套結果是一個多表查詢的 SQL 語句
會執行多條 SQL 語句 只有一條復雜的 SQL 語句(多表連接)
SQL語句編寫較為簡單 SQL語句編寫較為復雜

以下給出簡單代碼比較二則區別:

	<!-- 嵌套查詢:通過執行另外一條SQL映射語句來返回預期的特殊類型 -->
	<resultMap id="BaseResultMap" type="com.eucheng.eusys.eusyspersonnel.domain.Depts">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="parent_id" jdbcType="INTEGER" property="parentId"/>
        <result column="level" jdbcType="VARCHAR" property="level"/>
        <result column="remark" jdbcType="VARCHAR" property="remark"/>
    </resultMap>
    <resultMap id="DeptsWithChildren" extends="BaseResultMap" type="com.eucheng.eusys.eusyspersonnel.domain.Depts">
        <collection property="childrens" ofType="com.eucheng.eusys.eusyspersonnel.domain.Depts"
                    select="getAllDepartmentsByParentId" column="id"/>
    </resultMap>
	<select id="getAllDepartmentsByParentId" parameterType="java.lang.Integer" resultMap="DeptsWithChildren">
        select
        id, `name`, parent_id, `level`, remark
        from dept
        where parent_id = #{parent_id,jdbcType=INTEGER}
    </select>
	
	<!-- 嵌套結果:使用嵌套結果映射來處理重復的聯合結果的子集 -->
	<select id="findPersonById2" parameterType="Integer" 
	                                   resultMap="IdCardWithPersonResult2">
	    SELECT p.*,idcard.code
	    from tb_person p,tb_idcard idcard
	    where p.card_id=idcard.id 
	    and p.id= #{id}
	</select>
	<resultMap type="Person" id="IdCardWithPersonResult2">
	    <id property="id" column="id" />
	    <result property="name" column="name" />
	    <result property="age" column="age" />
	    <result property="sex" column="sex" />
	    <association property="card" javaType="IdCard">
	        <id property="id" column="card_id" />
	        <result property="code" column="code" />
	    </association>
	</resultMap>

嵌套查詢的執行過程是:

 ==>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ==> Parameters: -1(Integer)
 ====>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ====> Parameters: 0(Integer)
 ======>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ======> Parameters: 1(Integer)
 ========>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ========> Parameters: 2(Integer)
 <========      Total: 0
 ========>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ========> Parameters: 3(Integer)
 <========      Total: 0
 <======      Total: 2
 ======>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ======> Parameters: 4(Integer)
 ========>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ========> Parameters: 5(Integer)
 <========      Total: 0
 ========>  Preparing: select id, `name`, parent_id, `level`, remark from dept where parent_id = ?
 ========> Parameters: 6(Integer)
 <========      Total: 0
 <======      Total: 2
 .....以下差不多相同就不截取了

嵌套結果的執行過程是:

嘿嘿沒有不想寫,就是只有一個 SQL 語句,多表聯查的那種。看參考1人家截圖去。

嵌套查詢的弊端

嵌套查詢的N+1問題:

盡管嵌套查詢大量的簡化了存在關聯關系的查詢,但它的弊端也比較明顯:即所謂的N+1問題。關聯的嵌套查詢顯示得到一個結果集,然后根據這個結果集的每一條記錄進行關聯查詢。
現在假設嵌套查詢就一個(即resultMap 內部就一個association標簽),現查詢的結果集返回條數為N,那么關聯查詢語句將會被執行N次,加上自身返回結果集查詢1次,共需要訪問數據庫N+1次。如果N比較大的話,這樣的數據庫訪問消耗是非常大的!所以使用這種嵌套語句查詢的使用者一定要考慮慎重考慮,確保N值不會很大。
嵌套語句的查詢會導致數據庫訪問次數不定,進而有可能影響到性能。

摘自:mybatis的嵌套查詢與嵌套結果查詢的不同

總結

所以多表查詢還是用嵌套結果,而嵌套查詢應該用在單表,階級。比如上面的部門結構,因為不確定部門的子部門有多少層,所以沒有辦法使用嵌套結果查詢。

參考

探索嵌套查詢和嵌套結果這對孿生子的秘密!!!

mybatis的嵌套查詢與嵌套結果查詢的不同

mybatis 中文文檔 --- XML 映射器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM