`
直线曲线
  • 浏览: 46120 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

ResultMap之复杂结果映射

阅读更多
快下班了,多么希望能来杯 啊。
昨天下班回去后,看了13集的东北往事,然后又开始了mybatis的探秘。之前也学习过Hibernate,经过这几日对mybatis的了解,感觉它的mapper的确很简洁很容易掌握,比hibernate的学习周期会短。

resultMap是否有必要配置,这要取决于你要映射的结果的复杂程度。
如果是column名称与类型与属性名称与类型能对应上,那么mybatis会自动的寻找到它,也就没有必要配置了。
但是对于复杂类型来说,resultMap是必须配置的,以帮助mybatis完成结果与类对象的映射。

简单内容学习完后,在小test中我也在想‘1对1’、‘1对多’的时候如何mapper呢?怀着这种疑问,开始学习mybatis的高级一些的配置。好了,下面列举一下ResultMap的高级使用,或说非常神奇的地方。官方文档称——“这是个神奇的‘网站’”,呵呵,玩笑而已,不过的却是非常XX。
首先列举一下resultMap中标签:
*constructor –  类在实例化时,用来注入结果到构造方法中
  **idArg – ID 参数;标记结果作为 ID 可以帮助提高整体效能
  **arg –  注入到构造方法的一个普通结果
*id –  一个ID 结果;标记结果作为ID 可以帮助提高整体效能
*result –  注入到字段或JavaBean 属性的普通结果
*association –  一个复杂的类型关联;许多结果将包成这种类型
  **嵌入结果映射  –  结果映射自身的关联,或者参考一个
*collection –  复杂类型的集
  **嵌入结果映射  –  结果映射自身的集,或者参考一个
*iscriminator –  使用结果值来决定使用哪个结果映射
  **case –  基于某些值的结果映射
  ***嵌入结果映射  –  这种情形结果也映射它本身,因此可以包含很多相
同的元素,或者它可以参照一个外部的结果映射。

下面讲一下理解后自我的了解:
constructor对应的是构造方法,可以为构造方法提供参数。需要强调——配置的参数的顺序与类型必须与类的构造方法的参数顺序与类型严格匹配。
idArg是constructor的参数标签,并且这个标签传递的应该是能唯一标识这个类实例的。可以理解为主键。
arg同样也是constructor的参数标签,传递非主键属性的数据。(能有若干个arg)。

id将指定列的数据映射到能唯一标识对应的属性上,可以理解为主键。若constructor中传递了idArg,所以这个id就可以省略了。

result用于映射列与普通类型的属性,若column名称和属性名称匹配的话,这个可以省去的,可以有若干个result。

association解决“有一个”的映射。例如类A的对象中有一个类B对象时,将结果映射到B对象中,利用这个标签就能迎刃而解了。
可以用“关联查询”和“关联结果”两个方式实现。我认为最佳方式是“关联结果”。
下面介绍这两种方式:
1、“关联查询”
例如:
<resultMap id=”blogResult” type=”Blog”> 
<association property="author" column="blog_author_id"  
javaType="Author" select=”selectAuthor”/> 
</resultMap> 
<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”> 
SELECT * FROM BLOG WHERE ID = #{id} 
</select> 
<select id=”selectAuthor” parameterType=”int” resultType="Author"> 
SELECT * FROM AUTHOR WHERE ID = #{id} 
</select> 

注意association中的select属性,就是它告知mybatis完成‘author’的映射需要去找‘selectAuthor’这映射。其中‘blog_author_id’是作为‘selectAuthor’的参数。这种方式会导致“N+1”问题,所以不是最佳实践。

2、“关联结果”
例子:
<select id="selectBlog" parameterType="int" 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> 

要注意sql语句中用到了联合查询方式join。是个重点哦。

映射部分如下:
<resultMap id="blogResult" type="Blog"> 
<id property=”blog_id” column="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> 

注意association中的resultMap属性,映射‘author’时候会去找‘authorResult’映射。‘authorResult’映射中,可以注意到column的值都是上边的sql查询中的列名。如果想‘authorResult’这个映射能够重用,就可以如上设置。
另一种就是不打算重用,就可以如下实现了:
<association property="author" column="blog_author_id" 
 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"/> 
<association/> 


collection:用来处理映射对象中存在集合属性的情况。
其实现方式与association基本相似。注意collection的ofType属性,它表示集合中存放的类型,也就是集合映射的集合存放的类型。‘嵌套结果’作为最佳实践方式,首先介绍:
例子:
<select id="selectBlog" parameterType="int" 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>

注意其中同样是应用了联合查询join。
映射例子:
<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>

这个映射的具体属性映射就写在了collection中,如果要复用的话,可以提出来,用‘resultMap’替代之。

‘嵌套查询’的例子如下:
<resultMap id=”blogResult” type=”Blog”> 
<collection property="posts" javaType=”ArrayList” column="blog_id" 
ofType="Post" select=”selectPostsForBlog”/> 
</resultMap> 

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

<select id=”selectPostsForBlog” parameterType=”int” resultType="Author"> 
SELECT * FROM POST WHERE BLOG_ID = #{id} 
</select>

‘blog_id’作为参数传递给了‘selectPostForBlog’。当然这也会引起“N+1”问题。


最后:由于mybatis能自动完成列与属性的映射,所以映射可以简写,但是这有前提——列名和属性名相似且属性对应。若果不满足条件就需要在映射中明确映射关系。


分享到:
评论
1 楼 guihaoming 2012-07-24  
谢谢,最近刚好在学习mybatis,看了你的明白了mybatis的复杂映射了

相关推荐

Global site tag (gtag.js) - Google Analytics