Result Maps
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来, 并在一些情形下允许你做一些 JDBC 不支持的事情。 实际上,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。 ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。
你已经见过简单映射语句的示例了,但没有明确的 resultMap。比如:
select id, username, hashedPassword
from some_table
where id = #{id}
上述语句只是简单地将所有的列映射到 HashMap 的键上,这由 resultType 属性指定。 虽然在大部分情况下都够用,但是 HashMap 不是一个很好的领域模型。 你的程序更可能会使用 JavaBean 或 POJO(Plain Old Java Objects,普通 Java 对象)作为领域模型。 MyBatis 对两者都支持。看看下面这个 JavaBean:
packagecom.someapp.model;publicclassUser{privateintid;privateStringusername;privateStringhashedPassword;publicintgetId(){returnid;}publicvoidsetId(intid){this.id =id;}publicStringgetUsername(){returnusername;}publicvoidsetUsername(Stringusername){this.username =username;}publicStringgetHashedPassword(){returnhashedPassword;}publicvoidsetHashedPassword(StringhashedPassword){this.hashedPassword =hashedPassword;}}
基于 JavaBean 的规范,上面这个类有 3 个属性:id,username 和 hashedPassword。这些属性会对应到 select 语句中的列名。
这样的一个 JavaBean 可以被映射到 ResultSet,就像映射到 HashMap 一样简单。
select id, username, hashedPassword
from some_table
where id = #{id}
类型别名是你的好帮手。使用它们,你就可以不用输入类的完全限定名称了。比如:
select id, username, hashedPassword
from some_table
where id = #{id}
这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再基于属性名来映射列到 JavaBean 的属性上。如果列名和属性名没有精确匹配,可以在 SELECT 语句中对列使用别名(这是一个 基本的 SQL 特性)来匹配标签。比如:
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
ResultMap 最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显式地用到他们。 上面这些简单的示例根本不需要下面这些繁琐的配置。 出于示范的原因,让我们来看看最后一个示例中,如果使用外部的 resultMap 会怎样,这也是解决列名不匹配的另外一种方式。
引用它的语句使用 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:
select user_id, user_name, hashed_password
from some_table
where id = #{id}
如果世界总是这么简单就好了。
高级结果映射
MyBatis 创建的一个想法是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们不总都是这样。 如果有一个独立且完美的数据库映射模式,所有应用程序都可以使用它,那就太好了,但可惜也没有。 ResultMap 就是 MyBatis 对这个问题的答案。
比如,我们如何映射下面这个语句?
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 co