zoukankan      html  css  js  c++  java
  • mybatis resultMap之collection聚集两种实现方式

    最近做得项目用到了MyBatis处理一对多的映射关系,下面的两个方法中用到了集合的嵌套查询方法,下面仔细学习一下这两种方式

    聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
    不同情况需要告诉MyBatis 如何加载一个聚集。MyBatis 可以用两种方式加载:

    • select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活但会将执行多次嵌套的SQL语句。

    • resultMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。

    两种加载方式格式如下:

    集合的嵌套查询(select)

    <collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" column="关联主键ID(用于嵌套查询SQL语句传入参数,多个用逗号分开)" select="另一个select映射SQL的ID"/>
    
    <select parameterType="int" resultType="另一Java类名" id="另一个select映射SQL的ID">
    	SQL语句
    </select>
    
    <resultMap id="blogResult" type="Blog">  
    	<collection property="posts" javaType=”ArrayList” column="blog_id" ofType="Post" select="selectPostsForBlog"/>  
    </resultMap>  
       
    <select id="selectBlog" parameterType="int" resultMap="blogResult">  
    	SELECT * FROM BLOG WHERE ID = #{id}  
    </select>  
       
    <select id="selectPostsForBlog" parameterType="int" resultType="Author">  
    	SELECT * FROM POST WHERE BLOG_ID = #{id}  
    </select>
    

    注意:column属性的值必须与相应的SQL查询语句中的列名相同。MyBatis会将第一条SQL语句查询出来的该列的值用于所聚集的SQL映射语句的入参。因第一条SQL语句查询出来的每个该列的值都将用于执行另一个SQL语句,所以聚集的SQL语句将被多次执行

    虽然这个方法简单,但是对于大数据集或列表查询,就不尽如人意了。这个问题被称为“N+1 选择问题”(N+1 Selects Problem)。概括地说,N+1选择问题是这样产生的:

    您执行单条SQL语句去获取一个列表的记录( “+1”)。

    对列表中的每一条记录,再执行一个联合select 语句来加载每条记录更加详细的信息(“N”)。

    这个问题会导致成千上万的SQL语句的执行,因此并非总是可取的。

    上面的例子,MyBatis可以使用延迟加载这些查询,因此这些查询立马可节省开销。然而,如果您加载一个列表后立即迭代访问嵌套的数据,这将会调用所有的延迟加载,因此性能会变得非常糟糕。

    鉴于此,这有另外一种方式。

    集合的嵌套结果集(Nested Results for Collection)

    <resultMap id="resultMap的ID"  type="Java类名">
    	<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" resultMap="另一resultMap的ID"/>
    </resultMap>
      
    <resultMap="另一resultMap的ID" type="另一Java类名">
    	<id property="id" column="关联主键ID"/>
    	....
    </resultMap>
    
    <select id="selectBlog" parameterType="int" resultMap="blogResult">  
    	select  
    		B.id as blog_id,  
    		B.title as blog_title,  
    		B.author_id as blog_author_id,  
    		P.id as post_id,  
    		P.subject as post_subject,  
    		P.body as post_body,  
    	from Blog B  
    	left outer join Post P on B.id = P.blog_id  
    	where B.id = #{id}  
    </select>
    

    同样,我们把Blog和Post两张表连接在一起,并且也保证列标签名在映射的时候是唯一且无歧义的。现在将Blog和Post的集合映射在一起是多么简单:

    <resultMap id="blogResult" type="Blog">  
    	<id property="id" column="blog_id" />  
    	<result property="title" column="blog_title"/>  
    	<collection property="posts" ofType="Post">  
    		<id property="id" column="post_id"/>  
    		<result property="subject" column="post_subject"/>  
    		<result property="body" column="post_body"/>  
    	</collection>  
    </resultMap>  
    

    再次强调一下,id 元素是非常重要的。
    如果希望结果映射有更好的可重用性,您可以使用下面的方式:

    <resultMap id="blogResult" type="Blog">  
    	<id property="id" column="blog_id" />  
    	<result property="title" column="blog_title"/>  
    	<collection property="posts" ofType="Post" resultMap="blogPostResult"/>  
    </resultMap>  
       
    <resultMap id="blogPostResult" type="Post">  
    	<id property="id" column="post_id"/>  
    	<result property="subject" column="post_subject"/>  
    	<result property="body" column="post_body"/>  
    </resultMap>  
    

    注意:column属性的值必须与相应的SQL查询语句的列名一样。

  • 相关阅读:
    linux运维学习
    2017年阿里巴巴三面经验
    Spring Boot:在Spring Boot中使用Mysql和JPA
    meshroom和alicevision在Ubuntu16上的安装过程
    ubuntu rm -rf ntfs 硬盘恢复
    python 脚本内部修改 LD_LIBRARY_PATH
    python uml 图
    tlmgr 相关
    ubuntu 安装 clangd 10.0.0
    zsh 快捷键
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11864012.html
Copyright © 2011-2022 走看看