MyBatis 配置之集合的嵌套
前言介绍
在一些查询结果包装类中,包含一些 List 集合属性,使用 collection 标签可以声明该 List 集合中属性的类型,便于 MyBatis 对包装类中的集合类型属性进行映射。
代码示例
例如商城,取出某一个商品信息以及该商品的评价列表,其中商品包装类 Product 的定义代码如下:
1
2
3
4
5
6
7
8
9
10
|
package cn.com.mybatis.pojo;
public class Product{
//商品id
private int pid;
//商品名称
private String pname;
//商品的评价信息
private List<Reply> replys;
//get和set方法
}
|
此时,商品的评价信息就是一个 List,所以在定义结果映射配置时,使用 collection 来定义评价结果集合,示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
< resultMap id = "productResult" type = "cn.com.mybatis.pojo.Product" >
< id property = "pid" column = "product_id" />
< result property = "pname" column = "product_name" />
< collection property = "replys" select = "queryReplyByProductId" column = "product_id" ofType = "Reply" />
</ resultMap >
< select id = "queryProductInfo" parameterType = "int" resultMap = "productResult" >
select
P.id as product_id,
P.name as product_name
from product P WHERE P.id = #{id}
</ select >
< select id = "queryReplyByProductId" parameterType = "int" resultType = "Reply" >
select * from reply R WHERE R.pid = #{ProductId}
</ select >
|
以上示例中,Product 与商品评价 Reply 会进行关联,一个商品评价 Reply 的 pid 只对应一个商品 Product 的 id,而一个商品 Product 的 id 可对应多个商品评价 Reply 的 pid,是一对多的关系。
通过配置集合的嵌套结果,就可以将查询结果中的包装类的集合类型的属性嵌套到结果集中。通过上面的配置最终得到一个包含 Reply 的 List 的商品包装类 Product。
外部引用
collection 标签也可以引入外部的 resultMap 配置。如果 queryReplyByProductId 配置的 sql 查询结果中使用了别名,或数据库字段名与 Reply 类属性名不对应,此时需要返回一个名为 replyResult 的 resultMap,那么 productResult 中的 collection 可以做如下配置:
1
2
3
4
5
6
7
8
9
10
11
|
< resultMap id = "productResult" type = "cn.com.mybatis.pojo.Product" >
< id property = "pid" column = "product_id" />
< result property = "pname" column = "product_name" />
< collection property = "replys" ofType = "Reply" resultMap = "replyResult" columnPrefix = "reply_" >
</ resultMap >
< resultMap id = "replyResult" type = "Reply" >
< id property = "id" column = "id" />
< result property = "username" column = "username" />
< result property = "info" column = "info" />
</ resultMap >
|
columnPrefix 代表为外部引入的 resultMap 中的每一个元素的 column 属性加上一个前缀。
小结一下吧
在一些查询结果包装类中,包含一些 List 集合属性,可使用 collection 标签声明该 List 集合中属性的类型。以便于 MyBatis 对包装类中的集合类型属性进行映射。可以在 collection 标签中配置,也可以引入外部的 resultMap 做配置。
MyBatis 集合、集合嵌套查询
集合
1
2
3
4
5
|
< collection property = "posts" ofType = "domain.blog.Post" >
< id property = "id" column = "post_id" />
< result property = "subject" column = "post_subject" />
< result property = "body" column = "post_body" />
</ collection >
|
集合元素的作用几乎和关联是相同的。实际上,它们也很相似,文档的异同是多余的。 所以我们更多关注于它们的不同。
我们来继续上面的示例,一个博客只有一个作者。但是博客有很多文章。在博客类中, 这可以由下面这样的写法来表示:
1
|
private List< Post > posts;
|
要映射嵌套结果集合到 List 中,我们使用集合元素。就像关联元素一样,我们可以从 连接中使用嵌套查询,或者嵌套结果。
集合的嵌套查询
首先,让我们看看使用嵌套查询来为博客加载文章。
1
2
3
4
5
6
7
8
9
10
11
|
< resultMap id = "blogResult" type = "Blog" >
< collection property = "posts" javaType = "ArrayList" column = "id" ofType = "Post" select = "selectPostsForBlog" />
</ resultMap >
< select id = "selectBlog" resultMap = "blogResult" >
SELECT * FROM BLOG WHERE ID = #{id}
</ select >
< select id = "selectPostsForBlog" resultType = "Post" >
SELECT * FROM POST WHERE BLOG_ID = #{id}
</ select >
|
这里你应该注意很多东西,但大部分代码和上面的关联元素是非常相似的。首先,你应 该注意我们使用的是集合元素。然后要注意那个新的“ofType”属性。这个属性用来区分 JavaBean(或字段)属性类型和集合包含的类型来说是很重要的。所以你可以读出下面这个 映射:
1
|
< collection property = "posts" javaType = "ArrayList" column = "id" ofType = "Post" select = "selectPostsForBlog" />
|
读作: “在 Post 类型的 ArrayList 中的 posts 的集合。”
javaType 属性是不需要的,因为 MyBatis 在很多情况下会为你算出来。所以你可以缩短 写法:
1
|
< collection property = "posts" column = "id" ofType = "Post" select = "selectPostsForBlog" />
|
集合的嵌套结果
至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性
首先, 让我们看看 SQL:
1
2
3
4
5
6
7
8
9
10
11
12
|
< select id= "selectBlog" 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 >
|
我们又一次联合了博客表和文章表,而且关注于保证特性,结果列标签的简单映射。现 在用文章映射集合映射博客,可以简单写为:
1
2
3
4
5
6
7
8
9
|
< 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 >
|
同样,要记得 id 元素的重要性,如果你不记得了,请阅读上面的关联部分。
同样, 如果你引用更长的形式允许你的结果映射的更多重用,你可以使用下面这个替代 的映射:
1
2
3
4
5
6
7
8
9
10
11
|
< resultMap id = "blogResult" type = "Blog" >
< id property = "id" column = "blog_id" />
< result property = "title" column = "blog_title" />
< collection property = "posts" ofType = "Post" resultMap = "blogPostResult" columnPrefix = "post_" />
</ resultMap >
< resultMap id = "blogPostResult" type = "Post" >
< id property = "id" column = "id" />
< result property = "subject" column = "subject" />
< result property = "body" column = "body" />
</ resultMap >
|
注意 这个对你所映射的内容没有深度,广度或关联和集合相联合的限制。当映射它们 时你应该在大脑中保留它们的表现。
你的应用在找到最佳方法前要一直进行的单元测试和性 能测试。好在 myBatis 让你后来可以改变想法,而不对你的代码造成很小(或任何)影响。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/fageweiketang/article/details/80905295