resultMap 元素是 MyBatis 中最重要最强大的元素。它就是让你远离 90%的需要从结果 集中取出数据的 JDBC 代码的那个东西, 而且在一些情形下允许你做一些 JDBC 不支持的事 情。 事实上, 编写相似于对复杂语句联合映射这些等同的代码, 也许可以跨过上千行的代码。

ResultMap 的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系。

你已经看到简单映射语句的示例了,但没有明确的 resultMap。比如:

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

这样一个语句简单作用于所有列被自动映射到 HashMap 的键上,这由 resultType 属性 指定。这在很多情况下是有用的,但是 HashMap 不能很好描述一个领域模型。那样你的应 用程序将会使用 JavaBeans 或 POJOs(Plain Old Java Objects,普通 Java 对象)来作为领域 模型。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;
 }
}

基于 JavaBean 的规范,上面这个类有 3 个属性:id,username 和 hashedPassword。这些 在 select 语句中会精确匹配到列名。

这样的一个 JavaBean 可以被映射到结果集,就像映射到 HashMap 一样简单。

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

要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。比如:

<!-- In mybatis-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>

如果世界总是这么简单就好了。

高级结果映射
MyBatis 创建的一个想法:数据库不用永远是你想要的或需要它们是什么样的。而我们 最喜欢的数据库最好是第三范式或 BCNF 模式,但它们有时不是。如果可能有一个单独的 数据库映射,所有应用程序都可以使用它,这是非常好的,但有时也不是。结果映射就是 MyBatis 提供处理这个问题的答案。

比如,我们如何映射下面这个语句?

<!-- 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>

你可能想把它映射到一个智能的对象模型,包含一个作者写的博客,有很多的博文,每 篇博文有零条或多条的评论和标签。 下面是一个完整的复杂结果映射例子 (假设作者, 博客, 博文, 评论和标签都是类型的别名) 我们来看看, 。 但是不用紧张, 我们会一步一步来说明。 当天最初它看起来令人生畏,但实际上非常简单。

<!-- 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 元素有很多子元素和一个值得讨论的结构。 下面是 resultMap 元素的概念视图 
resultMap
constructor - 类在实例化时,用来注入结果到构造方法中 
    idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能
    arg- 注入到构造方法的一个普通结果
id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能
result – 注入到字段或 JavaBean 属性的普通结果
association – 一个复杂的类型关联;许多结果将包成这种类型 
    嵌入结果映射 – 结果映射自身的关联,或者参考一个 
collection – 复杂类型的集 
    嵌入结果映射 – 结果映射自身的集,或者参考一个
discriminator – 使用结果值来决定使用哪个结果映射 
    case – 基于某些值的结果映射 
        嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。

ResultMap Attributes

id:当前命名空间中的一个唯一标识,用于标识一个result map.
type:类的全限定名, 或者一个类型别名 (内置的别名可以参考上面的表格). 
autoMapping:如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属性会覆盖全局的属性autoMappingBehavior。默认值为:unset。

最佳实践 通常逐步建立结果映射。单元测试的真正帮助在这里。如果你尝试创建 一次创建一个向上面示例那样的巨大的结果映射, 那么可能会有错误而且很难去控制它 来工作。开始简单一些,一步一步的发展。而且要进行单元测试!使用该框架的缺点是 它们有时是黑盒(是否可见源代码) 。你确定你实现想要的行为的最好选择是编写单元 测试。它也可以你帮助得到提交时的错误。

下面一部分将详细说明每个元素。 
id & result

<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>

这些是结果映射最基本内容。id 和 result 都映射一个单独列的值到简单数据类型(字符 串,整型,双精度浮点数,日期等)的单独属性或字段。

这两者之间的唯一不同是 id 表示的结果将是当比较对象实例时用到的标识属性。这帮 助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射) 。

每个都有一些属性: 
Id and Result Attributes

property:映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同 的 JavaBeans 的属性,那么就会使用。否则 MyBatis 将会寻找给定名称 property 的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你 可以这样映射一些东西: “username” ,或者映射到一些复杂的东西: “address.street.number” 。 
column:从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会 传递给 resultSet.getString(columnName)方法参数中相同的字符串。 
javaType:一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名 的列表) 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。 然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的行为。 
jdbcType:在这个表格之后的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅 仅需要对插入,更新和删除操作可能为空的列进行处理。这是 JDBC jdbcType 的需要,而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定 这个类型-但仅仅对可能为空的值。 
typeHandler:我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默 认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理 器的实现,或者是类型别名。

关注微信公众号:IT哈哈(it_haha),学习更多知识。

MyBatis之Mapper XML 文件详解(三)-Result Maps的更多相关文章

  1. MyBatis之Mapper XML 文件详解(一)

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

  2. MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询

    支持的 JDBC 类型为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型. BITFLOATCHARTIMESTAMPOTHERUNDEFINEDTINY ...

  3. Mybatis的mapper.xml文件详解

    1.#{}和${}的区别: #{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo.hashmap.        如果接收简单类型,#{}中可以写成value或其它名称.      ...

  4. MyBatis之Mapper XML 文件详解(二)-sql和入参

    sql 这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中.它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如: <sql id="use ...

  5. Java数据持久层框架 MyBatis之API学习六(Mapper XML 文件详解)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  6. 笔记:MyBatis Mapper XML文件详解 - Result Maps

    Result Maps(结果集) resultMap 元素是 MyBatis 中最重要最强大的元素.它就是让你远离 90%的需要从结果 集中取出数据的 JDBC 代码的那个东西, 而且在一些情形下允许 ...

  7. 笔记:MyBatis Mapper XML文件详解 - 映射和参数

    MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

  8. 笔记:MyBatis Mapper XML文件详解 - Cache

    缓存(Cache) 从数据库中加载的数据缓存到内存中,是很多应用程序为了提高性能而采取的一贯做法.MyBatis对通过映射的SELECT语句加载的查询结果提供了内建的缓存支持.默认情况下,启用一级缓存 ...

  9. [转]AndroidManifest.xml文件详解

    转自:http://www.cnblogs.com/greatverve/archive/2012/05/08/AndroidManifest-xml.html AndroidManifest.xml ...

随机推荐

  1. thinkphp下通过页面链接传递的参数获取一次后失效

    在thinkphp下通过页面链接传递的参数获取一次后失效,ajax内部无法再次使用.想要使用必须再次用js获取其值,通过ajax传递给后台使用. 1.通过页面链接传递参数给下一页 2.可以再下一页后台 ...

  2. 查询多表集合(union)、查询时建临时字段、查询时给字段设置默认值

    () UNION () UNION (select i.create_time as time,i.investment_amount as amount,i.invest_state as stat ...

  3. Vue-resource和Axios对比以及Vue-axios

    vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios. vue-resource特点 vue-resource插件具有以下特点: 1,体积小 vue-resour ...

  4. HTML5数据存储方案data与jQuery数据存储方案$.data()的区别

    我们先看下$.fn.data()的使用,这个和$.data()是不一样的,前者是和某个jquery对象相关,后者则是全局方法.主要有data()和removeData()这2个实例方法.通过下面的例子 ...

  5. div居中方式

    1. position: absolute; top:50%:left: 50%; margin-top: -高度的一半; margin-left: -宽度的一半(此方法适用于固定宽高的元素) 注: ...

  6. SPOJ2666 QTREE4

    我是萌萌的传送门 我是另一个萌萌的传送门 一道树分治……简直恶心死了……我在调代码的时候只想说:我*************************************************…… ...

  7. 广告点击率预测(CTR) —— 在线学习算法FTRL的应用

    FTRL由google工程师提出,在13的paper中给出了伪代码和实现细节,paper地址:http://www.eecs.tufts.edu/~dsculley/papers/ad-click-p ...

  8. windows 打印刻录 代码规范及问题

    1.获取CString字节数 int z_Len = WideCharToMultiByte(CP_ACP, 0, z_FileXml.GetBuffer(), z_FileXml.GetLength ...

  9. 从SuperSocket的App.config中读取配置,并修改保存,再重启服务

    string XmlPath = System.Windows.Forms.Application.ExecutablePath + ".config"; XmlDocument ...

  10. [Errno 14] problem making ssl connection Trying other mirror.

    使用yum安装程序,报错 解决方法: 我的是升级了下curl就可以了   yum update curl