mybatis ---- 級聯查詢 一對多 (集合映射)

原文鏈接

關聯有嵌套查詢和嵌套結果兩種方式,本文是按照嵌套結果這種方式來說明的

上一章介紹了多對一的關係,用到了<association></association>,這是一個複雜類型的關聯。我們選擇一個示例來回顧下,比如:一個博客有一個用戶,關聯映射就工作於這種結果之上。首先看下,我們在本文中要用到的表結構字段:

[sql] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  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   
我們把一個博客和一個用戶關聯在一起,就像:

[sql] view plain copy
 在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.                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>  


注意這個聯合查詢,以及所有結果被唯一而清晰的名字而重命名。這使得映射非常簡單。現在我們可以映射這個結果:

[sql] view plain copy
 在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"  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 plain copy
 在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 plain copy
 在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>  
集合元素的作用和關聯幾乎是相同的。我們來繼續上面的示例,一個博客只有一個作者。但是博客有很多文章,在博客類中,這可以由下面的寫法來表示:
[sql] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. private List<Post> posts;   
這一次聯合博客表和文章表(一個blog_id可以對應很多的文章)SQL如下:
[html] view plain copy
 在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 plain copy
 在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>  

高級關聯和集合映射還有很多要琢磨的地方。就讓面介紹的集合映射,稍微的整理下(一個博客下面,有很多文章).
首先創建下,需要用到的表格,以及向其中插入一些數據. 
[sql] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  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','[email protected]','合肥的小男孩','旅遊');  
  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 plain copy
 在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 plain copy
 在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 plain copy
 在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 plain copy
 在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 plain copy
 在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 plain copy
 在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 plain copy
 在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. 靈域  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章