關聯有嵌套查詢和嵌套結果兩種方式,本文是按照嵌套結果這種方式來說明的
上一章介紹了多對一的關係,用到了<association></association>,這是一個複雜類型的關聯。我們選擇一個示例來回顧下,比如:一個博客有一個用戶,關聯映射就工作於這種結果之上。首先看下,我們在本文中要用到的表結構字段:
- 博客
- blog : id title author_id
- 作者
- author: id username password email bio favourite_section
- 文章
- post :id blog_id author_id created_on section subject draft body
- 評論
- comment : id post_id name comment
- 標籤
- T : id name
- <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_passowrd,
- a.email as auhtor_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>
注意這個聯合查詢,以及所有結果被唯一而清晰的名字而重命名。這使得映射非常簡單。現在我們可以映射這個結果:
- <resultMap id="blogResult" type="Blog">
- <id property="id" column="blog_id"/>
- <result property="title" column="blog_title"/>
- <!-- 和一個用戶關聯,Blog 類裏面屬性時author,關聯的列是原先的blog.author_id-->
- <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>
在上面的例子中,你可以看到博客的作者關聯authorResult 結果映射來加載作者實例。 上面的實例中,用了外部的結果映射元素來映射關聯。這使得Author結果映射可以重用。然而,你不需要重用它的話,或者你僅僅引用你所有的結果映射到一個單獨描述的結果映射中。你可以嵌套結果映射。這裏給出使用這種方式的相同示例:
- <resultMap id="blogResult" type="Blog">
- <id property="id" column="blog_id"/>
- <result property="title" column="blog_title"/>
- <!-- 和一個用戶關聯,Blog 類裏面屬性時author,關聯的列是原先的blog.author_id-->
- <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>
- </resultMap>
上面你已經看到了如何處理有一個類型的關聯.但是“有很多個”是怎樣的呢?,也就是集合類型,本文的主要工作是來說這個的。
集合
相對於關聯來說,集合映射多了一個屬性”ofType“.這個屬性用來區分JavaBean(或字段)屬性類型和集合包含的類型來說是很重要的. ,ofType用來表示集合包含類型。
- <collection property="posts" ofType="Post">
- <id property="id" column="post_id"/>
- <result property="subject" column="post_subject"/>
- <result property="body" column="post_body"/>
- </collection>
- private List<Post> posts;
這一次聯合博客表和文章表(一個blog_id可以對應很多的文章)SQL如下:
- <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>
- <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>
高級關聯和集合映射還有很多要琢磨的地方。就讓面介紹的集合映射,稍微的整理下(一個博客下面,有很多文章).
首先創建下,需要用到的表格,以及向其中插入一些數據.
- create table author(id int (11) not null auto_increment,
- username varchar(20) not null,
- password varchar(20) not null,
- email varchar(20) not null,
- bio varchar(20) not null,
- favourite_section varchar(20) not null,
- primary key(id)
- )ENGINE=InnoDB DEFAULT CHARSET=utf8;
- insert into author(id,username,password,email,bio,favourite_section)
- values(1001,'林楓','123456','[email protected]','合肥的小男孩','旅遊');
- create table blog (id int (11) not null auto_increment,
- title varchar(20) not null,
- author_id int(11) not null,
- primary key(id))
- ENGINE=InnoDB DEFAULT CHARSET=utf8;
- insert into blog(id,title,author_id) values(1,'小說博客',1001);
- create table post(id int (11) not null auto_increment,
- blog_id int(11) not null,
- author_id int(11) not null,
- created_on date not null,
- section varchar(20) not null,
- subject varchar(20) not null,
- draft varchar(20) not null,
- body varchar(20) not null,
- primary key(id)
- )ENGINE=InnoDB DEFAULT CHARSET=utf8;
- insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
- values(1,1,1001,now(),'旅遊','玄幻','草稿','絕世武神');
- insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
- values(2,1,1001,now(),'旅遊','玄幻','草稿','大主宰');
- insert into post(id,blog_id,author_id,created_on,section,subject,draft,body)
- values(3,1,1001,now(),'旅遊','玄幻','草稿','靈域');
在貼JAVA代碼之前,先看下目錄結構吧:
- package com.mybatis.model;
- /**
- * 作者類
- * @author Administrator
- *
- */
- public class Author {
- private int id;
- private String username;
- private String password;
- private String email;
- private String bio; //個人資料
- private String favourite_section; //最喜歡的。。
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public String getBio() {
- return bio;
- }
- public void setBio(String bio) {
- this.bio = bio;
- }
- public String getFavourite_section() {
- return favourite_section;
- }
- public void setFavourite_section(String favouriteSection) {
- favourite_section = favouriteSection;
- }
- }
- package com.mybatis.model;
- import java.util.List;
- /**
- * 博客類
- * @author Administrator
- *
- */
- public class Blog {
- private int id;
- private String title;
- private Author author;
- private List<Post> posts; //博客類有很多文章, 與post表中的blog_id對應
- public List<Post> getPosts() {
- return posts;
- }
- public void setPosts(List<Post> posts) {
- this.posts = posts;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public Author getAuthor() {
- return author;
- }
- public void setAuthor(Author author) {
- this.author = author;
- }
- }
文章類Post.,java
- package com.mybatis.model;
- import java.util.Date;
- /**
- * 文章類
- * @author Administrator
- *
- */
- public class Post {
- private int id;
- private int blog_id;
- private int author_id;
- private Date created_on;
- private String section;
- private String subject;
- private String draft;
- private String body;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getBlog_id() {
- return blog_id;
- }
- public void setBlog_id(int blogId) {
- blog_id = blogId;
- }
- public int getAuthor_id() {
- return author_id;
- }
- public void setAuthor_id(int authorId) {
- author_id = authorId;
- }
- public Date getCreated_on() {
- return created_on;
- }
- public void setCreated_on(Date createdOn) {
- created_on = createdOn;
- }
- public String getSection() {
- return section;
- }
- public void setSection(String section) {
- this.section = section;
- }
- public String getSubject() {
- return subject;
- }
- public void setSubject(String subject) {
- this.subject = subject;
- }
- public String getDraft() {
- return draft;
- }
- public void setDraft(String draft) {
- this.draft = draft;
- }
- public String getBody() {
- return body;
- }
- public void setBody(String body) {
- this.body = body;
- }
- }
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <typeAliases>
- <!-- 給實體類去一個別名 -->
- <typeAlias type="com.mybatis.model.Blog" alias="Blog"/>
- <typeAlias type="com.mybatis.model.Post" alias="Post"/>
- </typeAliases>
- <!-- 數據源配置,這裏用MySQL數據庫 -->
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC"/>
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
- <property name="username" value="root"/>
- <property name="password" value="123456"/>
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <mapper resource="com/mybatis/model/Blog.xml"/>
- </mappers>
- </configuration>
Blog.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC
- "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.mybatis.dao.IBlogDao">
- <!-- 用文章映射集合來映射博客 -->
- <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>
- <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>
- </mapper>
測試類Test.java
- package com.mybatis.test;
- import java.io.IOException;
- import java.util.List;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import com.mybatis.dao.IBlogDao;
- import com.mybatis.model.Blog;
- import com.mybatis.model.Post;
- public class Test {
- /***
- * 獲得MyBatis SqlSessionFactory
- * SqlSessionFactory 負責創建SqlSession ,一旦創建成功,就可以用SqlSession實例來執行映射語句
- * ,commit,rollback,close等方法
- * @return
- */
- private static SqlSessionFactory getSessionFactory(){
- SqlSessionFactory sessionFactory=null;
- String resource="configuration.xml";
- try {
- sessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource));
- } catch (IOException e) {
- e.printStackTrace();
- }
- return sessionFactory;
- }
- /**
- * main 方法
- * @param args
- */
- public static void main(String[] args) {
- SqlSession session=getSessionFactory().openSession();
- try {
- IBlogDao blogDao=session.getMapper(IBlogDao.class);
- Blog blog=blogDao.selectBlog(1);
- List<Post> postList=blog.getPosts();
- for(Post post:postList){
- System.out.println(post.getBody());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- finally{
- session.close();
- }
- }
- }
運行後結果如下:
- DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ooo Using Connection [com.mysql.jdbc.Connection@e00ed0]
- 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=?
- DEBUG [com.mybatis.dao.IBlogDao.selectBlog] - ==> Parameters: 1(Integer)
- 絕世武神
- 大主宰
- 靈域