mybats入门(四)resultMap

ResultMap

resultMap的元素是MyBatis中最重要最强大的元素。这就是您可以使用JDBC从ResultSet中检索数据的90%的代码,在某些情况下允许您执行JDBC甚至不支持的操作。事实上,编写复杂语句的连接映射等效代码可能会跨越数千行代码。ResultMap设计是这样的:简单的语句根本不需要显式的结果映射,而更复杂的语句只需要描述关系是绝对必要的。

您已经看到了没有显式resultMap的简单映射语句的例子例如:

<select id="selectUsers" resultType="map">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

这样的语句只会导致所有列自动映射到HashMap的键,如resultType属性所指定虽然在很多情况下很有用,但HashMap并不是一个很好的领域模型。更有可能的是,您的应用程序将为域模型使用JavaBean或POJO(Plain Old Java Objects)。MyBatis同时支持。考虑下面的JavaBean:

package com.someapp.model;
public class User {
  private int id;
  private String username;
  private String hashedPassword;
  
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }
  public String getHashedPassword() {
    return hashedPassword;
  }
  public void setHashedPassword(String hashedPassword) {
    this.hashedPassword = hashedPassword;
  }
}

基于JavaBeans规范,上面的类有3个属性:id,username和hashedPassword。这些与select语句中的列名完全匹配。

这样的JavaBean可以HashMap那样容易地映射到ResultSet。 

<select id="selectUsers" resultType="com.someapp.model.User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

请记住TypeAliases是你的朋友。使用它们,以便您不必继续输入班级的完全限定路径。例如:

<!-- In Config XML file -->
<typeAlias type="com.someapp.model.User" alias="User"/>

<!-- In SQL Mapping XML file -->
<select id="selectUsers" resultType="User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

在这些情况下,MyBatis 在后台自动创建一个ResultMap,以根据名称自动将列映射到JavaBean属性。如果列名不完全匹配,则可以在列名上使用select子句别名(标准SQL功能)以使标签匹配。例如:

<select id="selectUsers" resultType="User">
  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}
</select>

关于ResultMap的好处是你已经学到了很多关于它们的知识,但是你还没有看到它呢!这些简单的情况不需要比你在这里看到的更多。举例来说,让我们看看最后一个例子看起来像一个外部resultMap,这是解决列名不匹配的另一种方法。

<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap>

并且引用它的语句使用resultMap属性(注意我们移除了 resultType属性)。例如:

<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>

现在只要这个世界总是那么简单。

高级resultMap

resultMap的元素是MyBatis中最重要最强大的元素。这就是您可以使用JDBC从ResultSet中检索数据的90%的代码,在某些情况下允许您执行JDBC甚至不支持的操作。事实上,编写复杂语句的连接映射等效代码可能会跨越数千行代码。ResultMap设计是这样的:简单的语句根本不需要显式的结果映射,而更复杂的语句只需要描述关系是绝对必要的。

您已经看到了没有显式resultMap的简单映射语句的例子例如:

<!-- Very Complex Statement -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
  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,
       A.favourite_section as author_favourite_section,
       P.id as post_id,
       P.blog_id as post_blog_id,
       P.author_id as post_author_id,
       P.created_on as post_created_on,
       P.section as post_section,
       P.subject as post_subject,
       P.draft as draft,
       P.body as post_body,
       C.id as comment_id,
       C.post_id as comment_post_id,
       C.name as comment_name,
       C.comment as comment_text,
       T.id as tag_id,
       T.name as tag_name
  from Blog B
       left outer join Author A on B.author_id = A.id
       left outer join Post P on B.id = P.blog_id
       left outer join Comment C on P.id = C.post_id
       left outer join Post_Tag PT on PT.post_id = P.id
       left outer join Tag T on PT.tag_id = T.id
  where B.id = #{id}
</select>

这样的语句只会导致所有列自动映射到HashMap的键,如resultType属性所指定虽然在很多情况下很有用,但HashMap并不是一个很好的领域模型。更有可能的是,您的应用程序将为域模型使用JavaBean或POJO(Plain Old Java Objects)。MyBatis同时支持。考虑下面的JavaBean:

<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="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"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>

现在只要这个世界总是那么简单。

resultMap

  • constructor构造函数 - 用于在实例化时将结果注入到类的构造函数中
    • idArg - ID参数; 标记结果作为ID将有助于提高整体性能
    • arg - 注入构造函数的正常结果
  • id - 一个ID结果; 标记结果作为ID将有助于提高整体性能
  • result - 注入到字段或JavaBean属性中的正常结果
  • association - 一个复杂的类型协会; 许多结果将卷入这种类型
    • 嵌套的结果映射 - 关联是resultMap本身,或可以引用一个
  • collection - 复杂类型的集合
    • 嵌套的结果映射 - 集合本身就是resultMap,也可以引用其中的一个
  • discriminator - 使用结果值来确定使用 哪个resultMap
    • case - 一个案例是基于某种价值的结果图
      • 嵌套的结果映射 - 一个案例也是一个结果映射本身,因此可以包含许多这些相同的元素,或者它可以引用一个外部的resultMap。
ResultMap属性
属性 描述
id 此名称空间中的唯一标识符,可用于引用此结果映射。
type 完全限定的Java类名称或类型别名(请参阅上表中的内置类型别名列表)。
autoMapping 如果存在,MyBatis将启用或禁用此ResultMap的自动映射。该属性重写全局autoMappingBehavior。默认:未设置。

最佳实践始终逐步构建ResultMaps。单元测试真的有帮助。如果你试图像上面那样建立一个巨大的resultMap,那么很可能你会弄错了,而且很难一起工作。从简单开始,逐步发展一步。和单元测试!使用框架的缺点是它们有时是一个黑盒子(不管是否是开源的)。确保你达到你想要的行为的最好方法就是编写单元测试。提交错误时也有帮助。

ID&result
<id property = “id” column = “post_id” /> <result property = “subject” column = “post_subject” />  
  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值