1. 程式人生 > >MyBatis 關聯查詢(一對多 & 多對一)

MyBatis 關聯查詢(一對多 & 多對一)

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;成員變數。

去掉是為了便於理解一對多、多對一