关闭

mybatis ---- 级联查询 一对多 (集合映射)

14211人阅读 评论(3) 收藏 举报
分类:

关联有嵌套查询和嵌套结果两种方式,本文是按照嵌套结果这种方式来说明的

上一章介绍了多对一的关系,用到了<association></association>,这是一个复杂类型的关联。我们选择一个示例来回顾下,比如:一个博客有一个用户,关联映射就工作于这种结果之上。首先看下,我们在本文中要用到的表结构字段:

  1. 博客  
  2. blog :  id  title  author_id   
  3.   
  4. 作者  
  5. author:  id  username password email  bio favourite_section  
  6.   
  7. 文章  
  8. post :id  blog_id  author_id  created_on  section  subject  draft  body    
  9.   
  10. 评论  
  11. comment : id   post_id  name  comment    
  12.   
  13. 标签  
  14. T : id name   
我们把一个博客和一个用户关联在一起,就像:

  1. <select id="selectBlog" parameterType="int" resultMap="blogResult">  
  2.            select   
  3.                b.id as blog_id,  
  4.                b.title as blog_title,  
  5.                b.author_id as blog_author_id  
  6.                a.id as author_id,  
  7.                a.username as author_username,  
  8.                a.password as author_passowrd,  
  9.                a.email as auhtor_email,  
  10.                a.bio as author_bio  
  11.             from  blog b left outer join author a on b.author_id=a.id  
  12.                  where b.id=#{id}  
  13.     </select>  


注意这个联合查询,以及所有结果被唯一而清晰的名字而重命名。这使得映射非常简单。现在我们可以映射这个结果:

  1. <resultMap id="blogResult" type="Blog">  
  2.      <id property="id" column="blog_id"/>  
  3.       <result property="title" column="blog_title"/>  
  4.         
  5.       <!-- 和一个用户关联,Blog 类里面属性时author,关联的列是原先的blog.author_id-->  
  6.       <association property="author"  column="blog_author_id" javaType="Author"  resultMap="authorResult"/>  
  7. </resultMap>  
  8.   
  9. <resultMap id="authorResult" type="Author">  
  10.           <id property="id" column="author_id"/>  
  11.           <result property="username" column="author_username"/>  
  12.           <result property="password" column="author_password"/>  
  13.           <result property="email" column="author_email"/>  
  14.           <result property="bio" column="author_bio"/>  
  15. </resultMap>  

在上面的例子中,你可以看到博客的作者关联authorResult 结果映射来加载作者实例。  上面的实例中,用了外部的结果映射元素来映射关联。这使得Author结果映射可以重用。然而,你不需要重用它的话,或者你仅仅引用你所有的结果映射到一个单独描述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <resultMap id="blogResult" type="Blog">  
  2.      <id property="id" column="blog_id"/>  
  3.       <result property="title" column="blog_title"/>  
  4.         
  5.       <!-- 和一个用户关联,Blog 类里面属性时author,关联的列是原先的blog.author_id-->  
  6.       <association property="author"  column="blog_author_id" javaType="Author" >  
  7.               <id property="id" column="author_id"/>  
  8.               <result property="username" column="author_username"/>  
  9.               <result property="password" column="author_password"/>  
  10.               <result property="email" column="author_email"/>  
  11.               <result property="bio" column="author_bio"/>  
  12.       </association>  
  13. </resultMap>  

上面你已经看到了如何处理有一个类型的关联.但是“有很多个”是怎样的呢?,也就是集合类型,本文的主要工作是来说这个的


集合

相对于关联来说,集合映射多了一个属性”ofType“.这个属性用来区分JavaBean(或字段)属性类型集合包含的类型来说是很重要的. ,ofType用来表示集合包含类型。
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <collection property="posts"  ofType="Post">  
  2.        <id property="id" column="post_id"/>  
  3.        <result property="subject" column="post_subject"/>  
  4.        <result property="body" column="post_body"/>  
  5.  </collection>  
集合元素的作用和关联几乎是相同的。我们来继续上面的示例,一个博客只有一个作者。但是博客有很多文章,在博客类中,这可以由下面的写法来表示:
  1. private List<Post> posts;   
这一次联合博客表和文章表(一个blog_id可以对应很多的文章)SQL如下:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <select id="selectBlog" parameterType="int" resultMap="blogResult">  
  2.          select   
  3.              b.id as blog_id ,  
  4.              b.title as blog_title,  
  5.              b.author_id as blog_author_id,  
  6.              p.id as post_id,  
  7.              p.subject as post_subject,  
  8.              p.body as post_body  
  9.            from blog b  
  10.                left outer join  post p on b.id=p.blog_id  
  11.                where b.id=#{id}    
  12. </select>  
现在用“文章映射集合”来映射 “博客“,可以简单写为:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <resultMap id="blogResult" type="Blog">  
  2.     <id property="id" column="blog_id"/>  
  3.     <result property="title" column="blog_title"/>  
  4.     <collection property="posts" ofType="Post">  
  5.         <id property="id" column="post_id"/>  
  6.         <result property="subject" column="post_subject"/>  
  7.         <result property="body" column="post_body"/>  
  8.     </collection>  
  9. </resultMap>  

高级关联和集合映射还有很多要琢磨的地方。就让面介绍的集合映射,稍微的整理下(一个博客下面,有很多文章).
首先创建下,需要用到的表格,以及向其中插入一些数据. 
  1. create table author(id int (11) not null auto_increment,  
  2.                     username varchar(20) not null,  
  3.                     password varchar(20) not null,   
  4.                     email varchar(20) not null,  
  5.                     bio varchar(20) not null,  
  6.                     favourite_section varchar(20) not null,  
  7.                      primary key(id)  
  8.                   )ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  9.                     
  10.   
  11. insert into author(id,username,password,email,bio,favourite_section)   
  12. values(1001,'林枫','123456','824156593@qq.com','合肥的小男孩','旅游');  
  13.   
  14.           
  15.           
  16. create table blog (id int (11) not null auto_increment,  
  17.                     title varchar(20) not null,  
  18.                      author_id int(11) not null,  
  19.                       primary key(id))  
  20.                      ENGINE=InnoDB DEFAULT CHARSET=utf8;    
  21.    
  22.  insert into blog(id,title,author_id) values(1,'小说博客',1001);                      
  23.                        
  24. create table post(id int (11) not null auto_increment,  
  25.                   blog_id int(11) not null,  
  26.                   author_id int(11) not null,  
  27.                   created_on date not null,  
  28.                   section varchar(20) not null,  
  29.                   subject varchar(20) not null,  
  30.                   draft varchar(20) not null,  
  31.                   body varchar(20) not null,  
  32.                    primary key(id)  
  33.                     )ENGINE=InnoDB DEFAULT CHARSET=utf8;         
  34.                       
  35.                       
  36. insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)  
  37. values(1,1,1001,now(),'旅游','玄幻','草稿','绝世武神');    
  38.     
  39. insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)  
  40. values(2,1,1001,now(),'旅游','玄幻','草稿','大主宰');  
  41.   
  42. insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)  
  43. values(3,1,1001,now(),'旅游','玄幻','草稿','灵域');       

在贴JAVA代码之前,先看下目录结构吧:


作者类 Author.java
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.mybatis.model;  
  2. /** 
  3.  * 作者类 
  4.  * @author Administrator 
  5.  * 
  6.  */  
  7. public class Author {  
  8.       
  9.     private int id;  
  10.     private String username;  
  11.     private String password;  
  12.     private String email;  
  13.     private String bio; //个人资料  
  14.     private String favourite_section; //最喜欢的。。  
  15.       
  16.     public int getId() {  
  17.         return id;  
  18.     }  
  19.     public void setId(int id) {  
  20.         this.id = id;  
  21.     }  
  22.     public String getUsername() {  
  23.         return username;  
  24.     }  
  25.     public void setUsername(String username) {  
  26.         this.username = username;  
  27.     }  
  28.     public String getPassword() {  
  29.         return password;  
  30.     }  
  31.     public void setPassword(String password) {  
  32.         this.password = password;  
  33.     }  
  34.     public String getEmail() {  
  35.         return email;  
  36.     }  
  37.     public void setEmail(String email) {  
  38.         this.email = email;  
  39.     }  
  40.     public String getBio() {  
  41.         return bio;  
  42.     }  
  43.     public void setBio(String bio) {  
  44.         this.bio = bio;  
  45.     }  
  46.     public String getFavourite_section() {  
  47.         return favourite_section;  
  48.     }  
  49.     public void setFavourite_section(String favouriteSection) {  
  50.         favourite_section = favouriteSection;  
  51.     }  
  52.       
  53. }  
Blog.java
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.mybatis.model;  
  2.   
  3. import java.util.List;  
  4.   
  5. /** 
  6.  * 博客类 
  7.  * @author Administrator 
  8.  * 
  9.  */  
  10. public class Blog {  
  11.     private int id;  
  12.     private String title;  
  13.     private Author author;  
  14.     private List<Post> posts; //博客类有很多文章, 与post表中的blog_id对应  
  15.       
  16.     public List<Post> getPosts() {  
  17.         return posts;  
  18.     }  
  19.     public void setPosts(List<Post> posts) {  
  20.         this.posts = posts;  
  21.     }  
  22.     public int getId() {  
  23.         return id;  
  24.     }  
  25.     public void setId(int id) {  
  26.         this.id = id;  
  27.     }  
  28.     public String getTitle() {  
  29.         return title;  
  30.     }  
  31.     public void setTitle(String title) {  
  32.         this.title = title;  
  33.     }  
  34.     public Author getAuthor() {  
  35.         return author;  
  36.     }  
  37.     public void setAuthor(Author author) {  
  38.         this.author = author;  
  39.     }  
  40.       
  41. }  

文章类Post.,java
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.mybatis.model;  
  2.   
  3. import java.util.Date;  
  4.   
  5. /** 
  6.  * 文章类 
  7.  * @author Administrator 
  8.  * 
  9.  */  
  10. public class Post {  
  11.     private int id;  
  12.     private int blog_id;  
  13.     private int author_id;  
  14.     private Date created_on;  
  15.     private String section;  
  16.     private String subject;  
  17.     private String draft;  
  18.     private String body;  
  19.       
  20.     public int getId() {  
  21.         return id;  
  22.     }  
  23.     public void setId(int id) {  
  24.         this.id = id;  
  25.     }  
  26.     public int getBlog_id() {  
  27.         return blog_id;  
  28.     }  
  29.     public void setBlog_id(int blogId) {  
  30.         blog_id = blogId;  
  31.     }  
  32.     public int getAuthor_id() {  
  33.         return author_id;  
  34.     }  
  35.     public void setAuthor_id(int authorId) {  
  36.         author_id = authorId;  
  37.     }  
  38.     public Date getCreated_on() {  
  39.         return created_on;  
  40.     }  
  41.     public void setCreated_on(Date createdOn) {  
  42.         created_on = createdOn;  
  43.     }  
  44.     public String getSection() {  
  45.         return section;  
  46.     }  
  47.     public void setSection(String section) {  
  48.         this.section = section;  
  49.     }  
  50.     public String getSubject() {  
  51.         return subject;  
  52.     }  
  53.     public void setSubject(String subject) {  
  54.         this.subject = subject;  
  55.     }  
  56.     public String getDraft() {  
  57.         return draft;  
  58.     }  
  59.     public void setDraft(String draft) {  
  60.         this.draft = draft;  
  61.     }  
  62.     public String getBody() {  
  63.         return body;  
  64.     }  
  65.     public void setBody(String body) {  
  66.         this.body = body;  
  67.     }  
  68.       
  69. }  
总配置文件
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>     
  2. <!DOCTYPE configuration     
  3.     PUBLIC "-//mybatis.org//DTD Config 3.0//EN"     
  4.     "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  5. <configuration>  
  6.   <typeAliases>  
  7.     <!-- 给实体类去一个别名  -->  
  8.         <typeAlias type="com.mybatis.model.Blog" alias="Blog"/>   
  9.         <typeAlias type="com.mybatis.model.Post" alias="Post"/>  
  10.   </typeAliases>  
  11.     
  12.   <!-- 数据源配置,这里用MySQL数据库 -->  
  13.   <environments default="development">  
  14.      <environment id="development">  
  15.          <transactionManager type="JDBC"/>  
  16.          <dataSource type="POOLED">  
  17.                <property name="driver" value="com.mysql.jdbc.Driver"/>  
  18.                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>  
  19.                <property name="username" value="root"/>  
  20.                <property name="password" value="123456"/>  
  21.          </dataSource>  
  22.      </environment>  
  23.   </environments>  
  24.     
  25.   <mappers>  
  26.         <mapper resource="com/mybatis/model/Blog.xml"/>  
  27.   </mappers>  
  28.     
  29. </configuration>  

Blog.xml
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC   
  3.     "-//mybatis.org//DTD Mapper 3.0//EN"  
  4.     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.       
  6. <mapper namespace="com.mybatis.dao.IBlogDao">  
  7.   
  8. <!-- 用文章映射集合来映射博客 -->  
  9. <resultMap id="blogResult" type="Blog">  
  10.     <id property="id" column="blog_id"/>  
  11.     <result property="title" column="blog_title"/>  
  12.       
  13.     <!--文章集合 -->  
  14.     <collection property="posts" ofType="Post">  
  15.         <id property="id" column="post_id"/>  
  16.         <result property="subject" column="post_subject"/>  
  17.         <result property="body" column="post_body"/>  
  18.     </collection>  
  19. </resultMap>  
  20.   
  21. <select id="selectBlog" parameterType="int" resultMap="blogResult">  
  22.          select   
  23.              b.id as blog_id ,  
  24.              b.title as blog_title,  
  25.              b.author_id as blog_author_id,  
  26.              p.id as post_id,  
  27.              p.subject as post_subject,  
  28.              p.body as post_body  
  29.            from blog b  
  30.                left outer join  post p on b.id=p.blog_id  
  31.                where b.id=#{id}    
  32. </select>  
  33. </mapper>  

测试类Test.java
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.mybatis.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.List;  
  5.   
  6. import org.apache.ibatis.io.Resources;  
  7. import org.apache.ibatis.session.SqlSession;  
  8. import org.apache.ibatis.session.SqlSessionFactory;  
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
  10.   
  11. import com.mybatis.dao.IBlogDao;  
  12. import com.mybatis.model.Blog;  
  13. import com.mybatis.model.Post;  
  14.   
  15. public class Test {  
  16.       
  17.     /*** 
  18.      * 获得MyBatis SqlSessionFactory 
  19.      * SqlSessionFactory 负责创建SqlSession ,一旦创建成功,就可以用SqlSession实例来执行映射语句 
  20.      * ,commit,rollback,close等方法 
  21.      * @return 
  22.      */  
  23.     private static SqlSessionFactory getSessionFactory(){  
  24.         SqlSessionFactory sessionFactory=null;  
  25.         String resource="configuration.xml";  
  26.          try {  
  27.             sessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.         return sessionFactory;  
  32.     }  
  33.       
  34.     /** 
  35.      * main 方法 
  36.      * @param args 
  37.      */  
  38.     public static void main(String[] args) {  
  39.           
  40.           SqlSession session=getSessionFactory().openSession();  
  41.      try {  
  42.          IBlogDao blogDao=session.getMapper(IBlogDao.class);  
  43.          Blog blog=blogDao.selectBlog(1);  
  44.          List<Post> postList=blog.getPosts();  
  45.          for(Post post:postList){  
  46.              System.out.println(post.getBody());  
  47.          }  
  48.         } catch (Exception e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.         finally{  
  52.             session.close();  
  53.         }  
  54.     }  
  55. }  
运行后结果如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ooo Using Connection [com.mysql.jdbc.Connection@e00ed0]  
  2. DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ==>  Preparing: 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=?   
  3. DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ==> Parameters: 1(Integer)  
  4. 绝世武神  
  5. 大主宰  
  6. 灵域  
1
2

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7007969次
    • 积分:61454
    • 等级:
    • 排名:第34名
    • 原创:250篇
    • 转载:2617篇
    • 译文:3篇
    • 评论:663条
    文章分类
    最新评论