前面已經介紹了簡單的MyBatis單表操作,這里來用一個簡單的工程來演示下多表關聯。
工程創建參考MyBatis(一)單表操作
1.新建三張表(用戶表author, 文章表article, 評論表comment)
CREATE TABLE author (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
nickname VARCHAR(255),
birthday DATE,
register_time DATETIME NOT NULL
) default charset=utf8;
CREATE TABLE article (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
author INT NOT NULL,
create_time DATETIME NOT NULL,
modify_time DATETIME NOT NULL,
FOREIGN KEY (author) REFERENCES author (id)
) default charset=utf8;
CREATE TABLE comment (
id INT AUTO_INCREMENT PRIMARY KEY,
author INT NOT NULL,
article INT NOT NULL,
content TINYTEXT NOT NULL,
create_time DATETIME NOT NULL,
FOREIGN KEY (author) REFERENCES author (id),
FOREIGN KEY (article) REFERENCES article (id)
) default charset=utf8;
2.新建三個實體類(Author, Article, Comment)--get,set, 構造方法省略
public class Author {
private int id;
private String username;
private String nickname;
private Date birthday;
private Timestamp registerTime;
}
public class Article {
private int id;
private String title;
private String content;
private Author author;
private List<Comment> comments;
private Timestamp createTime;
private Timestamp modifyTime;
}
public class Comment {
private int id;
private String content;
private Author author;
private Article article;
private Timestamp createTime;
}
3.先看第一種查詢操作,第一章我們的例子中表中的列名和實體類中的屬性名是一一對應的,所以,查詢結果我們就直接用resultType來映射了,但是當列名和屬性名不一致的時候,resultType就不行了,所以才有了resultMap來指定每個列名和哪個屬性名對應,如下:
<select id="selectAuthor" resultMap="authorResult">
SELECT
id,
username,
nickname,
birthday,
register_time
FROM author
WHERE id = #{id}
</select>
<resultMap id="authorResult" type="Author">
<id property="id" column="id"/>
<result property="registerTime" column="register_time"/>
</resultMap>
上面的例子中:<id>用來映射主鍵,<result>用來映射一邊的屬性,如果列名和屬性名一樣,還可以省略映射關系。比如這里只指定registerTime屬性和register_time列名映射。
4. 第二種,多表查詢的第一種方式。比如我們要查詢某篇文章和對應的作者。先看例子:
<!-- 查詢作者 -->
<select id="selectAuthor" resultMap="authorResult">
SELECT
id,
username,
nickname,
birthday,
register_time
FROM author
WHERE id = #{id}
</select>
<resultMap id="authorResult" type="Author">
<id property="id" column="id"/>
<result property="registerTime" column="register_time"/>
</resultMap>
<!-- 查詢文章 -->
<select id="selectArticle" resultMap="articleMap">
SELECT
id,
title,
content,
author,
create_time,
modify_time
FROM article
WHERE id = #{id}
</select>
<resultMap id="articleMap" type="Article">
<id property="id" column="id"/>
<result property="createTime" column="create_time"/>
<result property="modifyTime" column="modify_time"/>
<!-- 嵌套查詢作者 -->
<association property="author" column="author" select="selectAuthor"/>
</resultMap>
上面的例子中,第一個select查詢只是一個簡單的單表查詢,第二個select查詢中也是一個簡單的單表查詢(看起來是),但是在resultMap中指定了一個association標簽,其中就指定著另一個select查詢的ID。MyBatis會在每一條查詢記錄上再執行一次association指定的查詢。以此來達到多表關聯查詢的目的。但是,很顯然,當數據量大的時候,這種方式的效率堪憂,因為每執行一次sql語句,我們還要執行一次association指定的查詢。所以一般使用下面的查詢方式:
5.第三種查詢方式。下面的例子中,我們查詢某篇文章對應的作者,以及對應的所有評論。
<select id="selectArticleDetails" resultMap="detailedArticleResultMap">
select
A.id as article_id,
A.title as article_title,
A.content as article_content,
A.create_time as article_createTime,
A.modify_time as article_modifyTime,
B.id as author_id,
B.username as author_username,
B.nickname as author_nickname,
B.birthday as author_birthday,
B.register_time as author_registerTime,
C.id as comment_id,
C.content as comment_content,
C.create_time as comment_createTime
from Article A
left outer join Author B on B.id = A.author
left outer join Comment C on A.id = C.article
where A.id = #{id}
</select>
<resultMap id="detailedArticleResultMap" type="Article">
<id property="id" column="article_id"/>
<result property="title" column="article_title"/>
<result property="content" column="article_content"/>
<result property="createTime" column="article_createTime"/>
<result property="modifyTime" column="article_modifyTime"/>
<!-- 指定某些實體類屬性對應的類型 -->
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="nickname" column="author_nickname"/>
<result property="birthday" column="author_birthday"/>
<result property="registerTime" column="author_registerTime"/>
</association>
<!-- 指定集合屬性對應的類型 -->
<collection property="comments" ofType="Comment" columnPrefix="comment_">
<id property="id" column="id"/>
<result property="content" column="content"/>
<result property="createTime" column="createTime"/>
</collection>
</resultMap>
單看查詢語句來說,這種查詢方式和我們平時使用的多表關聯查詢幾乎一模一樣,只是在resultMap中需要用association關鍵字來指定對應的映射,這里association指定的不再是一個select查詢的ID,而是resultMap屬性。同時用collection關鍵字指定集合屬性對應的類型和resultMap屬性。這里columnPrefix用來指定列名的前綴,result中的column就可以直接寫成content,而不用寫成comment_content了。
最后幫朋友打個小廣告