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” />