Mybatis中的高级映射

时间:2023-01-29 15:57:15

Mybatis的创建时基于这样一个思想:数据库并不是你想怎样就怎样的。虽然我们希望数据库遵守第三范式或者BCNF,但他们不是,如果有一个数据库能够完美映射到所有的应用数据模型,也是非常棒的,但也没有,结果集映射就是Mybats为解决这些问题而提供非解决方法,例如如何映射下面的语句?


!-- Very Complex Statement -->
<select id="selectBlogDetails" parameterType="int" 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" 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"/>
<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" column="post_author_id" javaType="Author"/>
<collection property="comments" column="post_id" ofType=" Comment">
<id property="id" column="comment_id"/>
</collection>
<collection property="tags" column="post_id" ofType=" Tag" >
<id property="id" column="tag_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>

这个resultMap的元素的子元素比较多,先从概念上概览一下resultMap

constructor---实例化的时候通过构造器将结果集注入到类中

      idArg----ID参数:将结果集标记为ID,以方便全局调用

      arg----注入构造器的结果集

id-----结果集ID,将结果集标记为ID。以方便全局调用

result---注入一个字段或者javabean属性的结果

association---复杂类型联合;许多查询结果合成这个leixing

         嵌套结果映射---associatios能引用自身,或者从其他地方引用

collection---复杂类型集合

         嵌套结果映射--collections能引用自身,或者从其他地方引用

discriminator---使用一个结果值以决定使用哪个resultMap

case – 基于不同值的结果映射  

     嵌套结果映射 –case也能引用它自身, 所以也能包含这些同样的元
素。它也可以从外部引用resultMap

 最佳实践: 逐步地生成resultMap,单元测试对此非常有帮助。如果您尝试一下子就
生成像上面这样巨大的resultMap,可能会出错,并且工作起来非常吃力。从简单地开
始,再一步步地扩展,并且进行单元测试。使用框架开发有一个缺点,它们有时像是一个
黑盒子。为了确保达到您所预想的行为,最好的方式就是进行单元测试。这对提交bugs
也非常有用