java版云笔记(八)之干映射

Mybatis关联映射

通过数据库对象期间的关联关系,反映至到实体对象之间的援。

加载多独表中的干数据,封装到我们的实业对象吃。

当事情对数据库进行关联查询。

关联

<association property="author" column="blog_author_id" javaType="Author">
  <id property="id" column="author_id"/>
  <result property="username" column="author_username"/>
</association>

关系元素处理“有一个”类型的关联。比如,在我们的示范中,一个博客有一个用户。关联映射就工作于这种结果上述。你指定了靶属性,来抱值的排列,属性之
java 类型(很多情形下 MyBatis 可以协调到底出来) ,如果需要的话还有 jdbc
类型,如果您想挂要获得的结果值还得种控制器。

涉中不同之是公需要报 MyBatis 如何加载关联。MyBatis
以这地方会发出个别种植不同的不二法门:

  • 嵌套查询:通过实践另外一个 SQL 映射语句来回到预期的繁杂类型。

  • 嵌套结果:使用嵌套结果映射来拍卖又的并结果的子集。首先,然让我们来查阅这因素的习性。所有的君还见面见到,它和平凡的独自出于
    select 和

resultMap 属性的结果映射不同。

  属性      描述  
property 映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的 property JavaBeans 的属性, 那么就会使用。否则 MyBatis 将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一 些 东 西 :“ username ”, 或 者 映 射 到 一 些 复 杂 的 东 西 : “address.street.number” 。
javaType 一个 Java 类的完全限定名,或一个类型别名 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。然而,如 javaType 果你映射到的是 HashMap,那么你应该明确地指定 javaType来保证所需的行为。
jdbcType 在这个表格之前的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅仅需要对插入, 更新和删除操作可能为空的列进行处理。这是 JDBC 的需要, jdbcType 而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定这个类型-但仅仅对可能为空的值。
typeHandler 默认的类型处理器。使用这个属性,你可以覆盖默认的 typeHandler 类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现, 或者是类型别名。

关联的嵌套查询

  属性   描述
column 来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字符串是相同的。 column 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
select 另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面有一个详细的示例。 select 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
fetchType 可选的。有效值为** lazy和eager。 如果使用了,它将取代全局配置参数lazyLoadingEnabled**。

示例:

<resultMap id="blogResult" type="Blog">
    <!-- property映射到读者实体类 -->
  <association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id="selectAuthor" resultType="Author">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>

  我们来三三两两只查询语句子:一个来加载博客,另外一个来加载作者,而且博客的结果映射描述了“selectAuthor”语句子应该于用来加载它的
author 属性。
其它兼具的习性将见面被自动加载,假设它们的排列和性名相匹配。

  这种方式非常简单,
但是对于大型数据集合和列表将无见面表现非常好。问题不怕是我们熟悉的 “N+1
查询问题
”。概括地谈,N+1 查询问题得以是这般引起的:

  •  你行了一个独的 SQL 语句来获取结果列表(就是“+1”)。

  • 对回的诸条记下,你行了一个查询语句来为每个加载细节(就是“N”)。
    其一题目会促成成千上万的 SQL 语句被实践。这便不是希望之。

  MyBatis
能延迟加载这样的查询就是一个便宜,因此而得散开这些讲话以运转的消耗。然而,如果您加载一个列表,之后迅速迭代来做客嵌套的数,你会调用所有的延迟加载,这样的行事容许是坏不好之。

  所以还有另外一栽办法。

提到的嵌套结果

  属性   描述
resultMap 这是结果映射的 ID,可以映射关联的嵌套结果到一个合适的对象图中。这是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到 resultMap 一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis 让你“链接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后面也有一个示例。
columnPrefix 当连接多表时,你将不得不使用列别名来避免ResultSet中的重复列名。指定columnPrefix允许你映射列名到一个外部的结果集中。 请看后面的例子。
notNullColumn 默认情况下,子对象仅在至少一个列映射到其属性非空时才创建。 通过对这个属性指定非空的列将改变默认行为,这样做之后Mybatis将仅在这些列非空时才创建一个子对象。 可以指定多个列名,使用逗号分隔。默认值:未设置(unset)。
autoMapping 如果使用了,当映射结果到当前属性时,Mybatis将启用或者禁用自动映射。 该属性覆盖全局的自动映射行为。 注意它对外部结果集无影响,所以在select or resultMap属性中这个是毫无意义的。 默认值:未设置(unset)。

在上面你就观望了一个非常复杂的嵌套关联的言传身教。下面是是一个非常简单的演示来说明它们怎么做事。代替了实施一个分手之话语,我们一齐博客表和作者表在联合,就比如:

<select id="selectBlog" resultMap="blogResult">
  select
    B.id            as blog_id,
    B.title         as blog_title,
    B.author_id     as blog_author_id,
    A.id            as author_id,
    A.username      as author_username,
    A.password      as author_password,
    A.email         as author_email,
    A.bio           as author_bio
  from Blog B left outer join Author A on B.author_id = A.id
  where B.id = #{id}
</select>

  注意这联手查询,
以及采用保护来保管有结果吃唯一以清晰的讳来重新命名。这令映射非常简单。现在咱们好投这个结果:

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>

<resultMap id="authorResult" type="Author">
  <id property="id" column="author_id"/>
  <result property="username" column="author_username"/>
  <result property="password" column="author_password"/>
  <result property="email" column="author_email"/>
  <result property="bio" column="author_bio"/>
</resultMap>

  可怜重大:
id元素在嵌套结果映射中串着好关键之角色。你应该总是指定一个或者多单可以唯一标识结果的属性。实际上要你莫点名它吧,
MyBatis仍然可干活,但是会产生严重的性质问题。在可以唯一标识结果的状况下,
尽可能少的选取属性。主键是一个强烈的取舍(即使是复合主键)。

  现在,点的言传身教用了表的结果映射元素来映射关联。这叫 Author
结果映射可以选用。然而,如果您不待选定它吧,或者你才引用你有着的结果映射合到一个独立描述的结果映射中。你可以嵌套结果映射。

  这里吃起用这种办法的均等示例(嵌套结果映射):

    <resultMap id="blogResult" type="Blog">
      <id property="id" column="blog_id" />
      <result property="title" column="blog_title"/>
      <association property="author" javaType="Author" javaType="Author" select="authorResult">
        <id property="id" column="author_id"/>
        <result property="username" column="author_username"/>
        <result property="password" column="author_password"/>
        <result property="email" column="author_email"/>
        <result property="bio" column="author_bio"/>
      </association>




    </resultMap>    

    <!--select的值和id的值要一样 -->
    <select id="authorResult" resultType="Author"> 
        <!-- sql语句 --->
    </select> 
    <!-- resultMap的id和resultMap值一样 -->
    <select id="getById" parameterType="int" resultMap="blogResult" > 
        <!-- sql语句 --->
    </select> 

使blog有一个co-author怎么收拾? select语句以扣押起是法

<select id="selectBlog" resultMap="blogResult">
  select
    B.id            as blog_id,
    B.title         as blog_title,
    A.id            as author_id,
    A.username      as author_username,
    A.password      as author_password,
    A.email         as author_email,
    A.bio           as author_bio,
    CA.id           as co_author_id,
    CA.username     as co_author_username,
    CA.password     as co_author_password,
    CA.email        as co_author_email,
    CA.bio          as co_author_bio
  from Blog B
  left outer join Author A on B.author_id = A.id
  left outer join Author CA on B.co_author_id = CA.id
  where B.id = #{id}
</select>

坐结果遭到之列名与resultMap中的列名不同。
你得指定columnPrefix去用映射co-author结果的resultMap。

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <association property="author"
    resultMap="authorResult" />
  <association property="coAuthor"
    resultMap="authorResult"
    columnPrefix="co_" />
</resultMap>

集合

    <collection property="posts" ofType="domain.blog.Post">
      <id property="id" column="post_id"/>
      <result property="subject" column="post_subject"/>
      <result property="body" column="post_body"/>
    </collection>

  集合元素的企图几乎和关系是平之。实质上,它们啊死相似,文档的异同是多余的。所以我们再多关心于它的两样。

  我们来持续上面的演示,一个博客只发生一个作者。但是博客有众多篇。在博客类中,
这得由下这样的写法来代表:

    private List<Post> posts;

  要投嵌套结果集合到 List
中,我们采取集合元素。就比如提到元素一样,我们得以自连着以嵌套查询,或者嵌套结果

会合的嵌套查询

  首先,让咱省用嵌套查询来啊博客加载文章

    <resultMap id="blogResult" type="Blog">
      <collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
    </resultMap>

    <select id="selectBlog" resultMap="blogResult">
      SELECT * FROM BLOG WHERE ID = #{id}
    </select>

    <select id="selectPostsForBlog" resultType="Post">
      SELECT * FROM POST WHERE BLOG_ID = #{id}
    </select>

  这里您当小心多物,但大多数代码和点的关系元素是异常相像之。首先,你应当小心我们应用的凡集合元素。然后要顾充分新的“ofType”属性。这个特性用来区别
JavaBean(或字段)属性类型以及集合包含的类
来说是不行重大的。所以您得读来脚是映射:

    <collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>

  读作: “在 Post 类型的 ArrayList 中的 posts 的集合。”

  javaType 属性是匪需之,因为 MyBatis
在许多状下会为而到底出来。所以你可以缩短写法:

    <collection property="posts" column="id" ofType="Post" select="selectPostsForBlog"/>

聚拢的嵌套结果

  至此,你可以猜测集合的嵌套结果是如何来干活之,因为它和关联完全相同,除了它以了一个“ofType”属性

  首先,让咱看一下SQL:

    <select id="selectBlog" 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>

  我们而同样赖手拉手了博客表和文章表明,而且关注于保证特性,结果列标签的简易映射。现在所以文章投集合映射博客,可以简简单单写啊:

    <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 元素的最主要MyBatis,如果你切莫记得了,请看者的干有。

  同样, 如果你引用更增长的款式允许而的结果映射的重复多选用,
你可利用下这个代表的投:

    <resultMap id="blogResult" type="Blog">
      <id property="id" column="blog_id" />
      <result property="title" column="blog_title"/>
      <collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/>
    </resultMap>

    <resultMap id="blogPostResult" type="Post">
      <id property="id" column="id"/>
      <result property="subject" column="subject"/>
      <result property="body" column="body"/>
    </resultMap>

   注意
:这个针对你所投的情节从未有过深度,广度或关系和聚集相并之范围。当照它们常若应有以大脑受到保存它的呈现。你的以在找到最佳办法前使直开展的单元测试和性能测试。好于
myBatis 让您后来可转想法,而不对准您的代码造成很有点(或其它)影响。

网站地图xml地图