一对多关系映射
上一节我们讲的是一对一的关系,这集我们来看一对多的关系。现在我们假设一个账号发表了多篇文章,所以添加一个文章表和一个文章实体类。
创建文章表和实体类
建表 SQL(简化示例):
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Title` varchar(100) NOT NULL,
`AID` int(11) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;Code language: JavaScript (javascript)
Article 实体类:
package cn.foxdevelop.models;
public class Article {
private int ID;
private String Title;
private int AID;
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public int getAID() {
return AID;
}
public void setAID(int aID) {
AID = aID;
}
}Code language: PHP (php)
修改 Account 类
在 Account 类中增加一个 Article 列表对象:
private List<Article> articles;
public List<Article> getArticles() {
return articles;
public void setArticles(List<Article> articles) {
this.articles = articles;
}Code language: PHP (php)
方式一:连表查询 + resultMap 映射
先往 Article 表中插入两条数据,都属于 Account 表中 ID 为 36 的用户。
SQL 语句:
SELECT * FROM account a, accountextend ae, article art
WHERE a.ExtendID = ae.ID AND a.ID = art.AID AND a.ID = 36
映射文件配置:
<select id="getAccountAndArticles" parameterType="int" resultMap="AccountAndArticlesResultMap3">
SELECT a.*, ae.ID AS EID, ae.EnglishName, art.ID AS artID, art.Title
FROM account a, accountextend ae, article art
WHERE a.ExtendID = ae.ID AND a.ID = art.AID AND a.ID = #{id}
</select>
<resultMap type="cn.foxdevelop.models.Account" id="AccountAndArticlesResultMap3">
<id property="ID" column="ID"/>
<result property="Name" column="Name"/>
<result property="Age" column="Age"/>
<association property="accountExtend" javaType="cn.foxdevelop.models.AccountExtend">
<id property="ID" column="EID"/>
<result property="EnglishName" column="EnglishName"/>
</association>
<collection property="articles" ofType="cn.foxdevelop.models.Article">
<id property="ID" column="artID"/>
<result property="Title" column="Title"/>
</collection>
</resultMap>Code language: HTML, XML (xml)
执行代码:
Account account = session.selectOne("cn.foxdevelop.mapper.getAccountAndArticles", 36);
System.out.println(account.getName() + " - " + account.getAccountExtend().getEnglishName());
for (Article a : account.getArticles()) {
System.out.println(a.getTitle());
}Code language: JavaScript (javascript)
输出结果:
张三 - zhangsan
不见不散
鸿雁
方式二:嵌套查询(分步查询)
映射文件配置:
<select id="getAccountAndArticles2" parameterType="int" resultMap="AccountAndArticlesResultMap4">
select * from Account where id=#{id}
</select>
<resultMap type="cn.foxdevelop.models.Account" id="AccountAndArticlesResultMap4">
<association property="accountExtend" column="ExtendID" select="getAccountExtend"/>
<collection property="articles" ofType="cn.foxdevelop.models.Article" column="ID" select="getArticle"/>
</resultMap>
<select id="getAccountExtend" parameterType="int" resultType="cn.foxdevelop.models.AccountExtend">
SELECT * FROM AccountExtend WHERE id=#{id}
</select>
<select id="getArticle" parameterType="int" resultType="cn.foxdevelop.models.Article">
SELECT * FROM Article WHERE AID=#{id}
</select>Code language: HTML, XML (xml)
注意:最后查询文章时是通过 AID 列与 Account 表的 ID 关联的。
两种方式对比
第一种连表查询只查一次数据库,在多数情况下性能会比第二种嵌套查询(查两次)更好。但第二种方式代码结构更清晰,适合复杂场景按需选择。
Previous: 一对一关系映射
Next: MyBatis 调用存储过程