MyBatis 關聯查詢(一對多 & 多對一)
阿新 • • 發佈:2018-11-05
1、一對多
舉個例子:一個國家有很多人。一對多
1)表結構
-- 國家country
CREATE TABLE `country` (
`cid` int(5) NOT NULL AUTO_INCREMENT,
`cname` varchar(20) NOT NULL,
PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 人people CREATE TABLE `people` ( `pid` int(5) NOT NULL AUTO_INCREMENT, `pname` varchar(20) NOT NULL, `countryId` int(5) NOT NULL, PRIMARY KEY (`pid`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
在資料庫中,哪個表裡面有外來鍵,則就是多方
2)實體類
//國家
public class Country {
private Integer cid;
private String cname;
private Set<People> peoples;
//省略get set屬性方法
@Override
public String toString() {
return "Country [cid=" + cid + ", cname=" + cname + ", peoples="
+ peoples + "]";
}
}
//人 public class People { private Integer pid; private String pname; private Integer countryId; //省略get set屬性方法 @Override public String toString() { return "People [pid=" + pid + ", pname=" + pname + ", countryId=" + countryId + "]"; } }
3)Dao介面
public interface ICountryDao {
Country selectById(int id);
Country selectById2(int id);
}
4)mapper.xml檔案
<!-- 方法1 多表連線查詢方式 --> <resultMap type="Country" id="countryMapper"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> <collection property="peoples" ofType="People"> <id column="pid" property="pid"/> <result column="pname" property="pname"/> </collection> </resultMap> <select id="selectById" resultMap="countryMapper"> select cid,cname,pid,pname from country,people where cid=countryId and cid = #{xxx} </select> <!-- 方法2 多表單獨查詢方式 --> <select id="selectPeople" resultType="People"> select pid,pname from people where countryId=#{ooo} </select> <resultMap type="Country" id="countryMapper2"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> <collection property="peoples" ofType="People" select="selectPeople" column="cid" /> </resultMap> <select id="selectById2" resultMap="countryMapper2"> select cid,cname from country where cid = #{xxx} </select>
方式一是將多張表先進行連線,連為一張表後進行查詢。其查詢本質是一張表。也只有一個select
<collection />是集合的意思,即有多個物件。
property:指定關聯屬性,即Country類中的集合屬性
ofType:集合屬性的泛型型別
方式二是將主表的查詢結果聯合其他表的查詢結果,封裝成一個物件。主表的查詢結果中的資料,作為其他表查詢的條件。
這多個查詢是可以跨越多個對映檔案的,即可以跨越多個namespace的。使用時,新增上其所在的namespace即可
關聯屬性<collection />的資料來源於另一個查詢selectPeople,該查詢<selectPeople />的動態引數countryId=#{ooo}的值則來自於查詢<selectById2 />的查詢結果欄位cid
5)測試輸出
方式一:
[DEBUG] ==> Preparing: select cid,cname,pid,pname from country,people where cid=countryId and cid = ?
[DEBUG] ==> Parameters: 3(Integer)
[TRACE] <== Columns: cid, cname, pid, pname
[TRACE] <== Row: 3, 日本, 1, 新垣結衣
[TRACE] <== Row: 3, 日本, 5, 鬆島楓
[DEBUG] <== Total: 2
Country [cid=3, cname=日本, peoples=[People [pid=5, pname=鬆島楓, countryId=null], People [pid=1, pname=新垣結衣, countryId=null]]]
方式二
[DEBUG] ==> Preparing: select cid,cname from country where cid = ?
[DEBUG] ==> Parameters: 2(Integer)
[TRACE] <== Columns: cid, cname
[TRACE] <== Row: 2, 美國
[DEBUG] ====> Preparing: select pid,pname from people where countryId=?
[DEBUG] ====> Parameters: 2(Integer)
[TRACE] <==== Columns: pid, pname
[TRACE] <==== Row: 3, 安妮·海瑟薇
[DEBUG] <==== Total: 1
[DEBUG] <== Total: 1
Country [cid=2, cname=美國, peoples=[People [pid=3, pname=安妮·海瑟薇, countryId=null]]]
2、多對一
反過來,多個人對一個國家。每個人只對一個國家。當然不考慮雙重國籍的吵架問題。
由於查詢多物件時,也是一個一個查的。所以:一對一關聯查詢的實現方式與多對一的實現方式是相同的。
1)實體類稍有變化:
//國家
public class Country {
private Integer cid;
private String cname;
//省略get set屬性方法
@Override
public String toString() {
return "Country [cid=" + cid + ", cname=" + cname + "]";
}
}
//人
public class People {
private Integer pid;
private String pname;
private Integer countryId;
private Country country;
//省略get set屬性方法
@Override
public String toString() {
return "People [pid=" + pid + ", pname=" + pname + ", countryId="
+ countryId + ", country=" + country + "]";
}
}
國家沒有了Set<People>人成員變數,人有了國家成員變數
2)Dao介面
public interface IPeopleDao {
People selectById(int id);
People selectById2(int id);
}
3)mapper.xml配置檔案
<!-- 方法1 多表連線查詢方式 -->
<resultMap type="People" id="peopleMapper">
<id column="pid" property="pid"/>
<result column="pname" property="pname"/>
<association property="country" javaType="Country">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</association>
<!-- 用集合的方式盡然可以,集合無非是一個國家的集合 -->
<!--
<collection property="country" ofType="Country">
<id column="cid" property="cid"/>
<result column="cname" property="cname"/>
</collection>
-->
</resultMap>
<select id="selectById" resultMap="peopleMapper">
select pid,pname,cid,cname
from people,country
where pid = #{xxx} and countryId=cid
</select>
<!-- 方法2 多表單獨查詢方式 -->
<select id="selectCountry" resultType="Country">
select cid,cname from country where cid=#{ooo}
</select>
<resultMap type="People" id="peopleMapper2">
<id column="pid" property="pid"/>
<result column="pname" property="pname"/>
<association property="country"
javaType="Country"
select="selectCountry"
column="countryId" />
</resultMap>
<select id="selectById2" resultMap="peopleMapper2">
select pid,pname,countryId from people where pid = #{xxx}
</select>
方式一<association />標籤體現出2個實體物件之間的關聯關係,一對一時用。
property:指定關聯屬性,即People類中的country屬性
javaType:關聯屬性的型別
4)測試輸出
方式一:
[DEBUG] ==> Preparing: select pid,pname,cid,cname from people,country where pid = ? and countryId=cid
[DEBUG] ==> Parameters: 5(Integer)
[TRACE] <== Columns: pid, pname, cid, cname
[TRACE] <== Row: 5, 鬆島楓, 3, 日本
[DEBUG] <== Total: 1
People [pid=5, pname=鬆島楓, countryId=null, country=Country [cid=3, cname=日本]]
方式二:
[DEBUG] ==> Preparing: select pid,pname,countryId from people where pid = ?
[DEBUG] ==> Parameters: 5(Integer)
[TRACE] <== Columns: pid, pname, countryId
[TRACE] <== Row: 5, 鬆島楓, 3
[DEBUG] ====> Preparing: select cid,cname from country where cid=?
[DEBUG] ====> Parameters: 3(Integer)
[TRACE] <==== Columns: cid, cname
[TRACE] <==== Row: 3, 日本
[DEBUG] <==== Total: 1
[DEBUG] <== Total: 1
People [pid=5, pname=鬆島楓, countryId=null, country=Country [cid=3, cname=日本]]
備註:
Country類中可以不刪除Set<People> peoples ; 成員變數。
People類中可以一直有Country country;成員變數。
去掉是為了便於理解一對多、多對一