我都知道Java對(duì)象存在三種關(guān)聯(lián)關(guān)系:一對(duì)一、一對(duì)多、多對(duì)多。本文將詳細(xì)講解MyBatis的關(guān)聯(lián)查詢方式。
關(guān)聯(lián)元素
- 一對(duì)一關(guān)系:association
- 一對(duì)多關(guān)系:collection
- 鑒別器映射:discriminator
查詢方式
無論是一對(duì)一還是一對(duì)多都存在兩種查詢方式
嵌套結(jié)果:通過查詢結(jié)果進(jìn)行映射至相應(yīng)的JavaBean(例如連接查詢)
嵌套查詢:先查一張表,然后通過這張表的結(jié)果去查其他表
數(shù)據(jù)庫表關(guān)系
現(xiàn)在有三張表,表字段如下
- company:
| id | code | name | source | create_time |
|---|
- company_ext:
| id | remark | create_time |
|---|
- company_price:
| id | company_id | date | price | create_time | update_time |
|---|
其中company.id與company_ext.id對(duì)應(yīng),且為一對(duì)一的關(guān)系。
company.id與company_price.company_id對(duì)應(yīng),即為一對(duì)多的關(guān)系。
JavaBean
這里只列出屬性名,set、get等方法,省略
public class Company {
private String id;
private String code;
private String name;
private String source;
private Date createTime;
......
}
public class CompanyExt {
private String id;
private String remark;
private Date createTime;
......
}
public class CompanyAndExt {
private String id;
private String code;
private String name;
private String source;
private Date createTime;
private CompanyExt companyExt;
......
}
public class StockPrice {
private String id;
private String companyId;
private String date;
private String price;
private String createTime;
......
}
public class CompanyPrice {
private String id;
private String code;
private String name;
private String source;
private Date createTime;
private List<StockPrice> stockPriceList;
......
}
接口類:
package com.test.mapper;
import java.util.List;
import com.test.dto.*;
import org.apache.ibatis.annotations.Param;
public interface CompanyMapper {
// 一對(duì)一
// 嵌套結(jié)果、嵌套查詢
CompanyAndExt getCompanyAndExtById(String id);
// 嵌套查詢
CompanyExt getCompanyExtById(String id);
// 一對(duì)多
// 嵌套結(jié)果、嵌套查詢
CompanyPrice getCompanyPriceById(String id);
// 嵌套查詢
List<StockPrice> listStockPriceByCompanyId(String companyId);
}
一對(duì)一(association)
- 嵌套結(jié)果
a. association常用元素如下
property:所映射的屬性名
javaType:所映射的屬性對(duì)應(yīng)的Java屬性類型
resultMap:使用已有的resultMap
columnPrefix:子標(biāo)簽result(id)的column的前綴
b. 示例源碼
<!--一對(duì)一的嵌套結(jié)果-->
<resultMap id="companyResultMap" type="com.test.dto.Company">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="name" column="name"/>
<result property="source" column="source"/>
<result property="createTime" column="create_time"/>
</resultMap>
<resultMap id="companyAndExtResultMap" extends="companyResultMap" type="com.test.dto.CompanyAndExt">
<association property="companyExt" javaType="com.test.dto.CompanyExt" columnPrefix="ext_">
<id column="id" property="id" />
<result column="remark" property="remark" />
<result column="create_time" property="createTime" />
</association>
</resultMap>
<select id="getCompanyAndExtById" resultMap="companyAndExtResultMap">
SELECT c.`id`,c.`code`,c.`name`,c.`source`,c.`create_time`, ce.`id` ext_id, ce.`remark` ext_remark, ce.`create_time` ext_create_time FROM company c, company_ext ce WHERE c.`id` = ce.`id` AND c.`id` = #{id,jdbcType=VARCHAR};
</select>
補(bǔ)充:
resultMap 下的extends元素,顧名思義,可以繼承另外一個(gè)resultMap的映射配置
關(guān)聯(lián)表查詢時(shí),使用前綴對(duì)后期的維護(hù)提供很大的便利
- 嵌套查詢
a. association常用元素如下
select:使用嵌套查詢方法
column:主查詢的結(jié)果作為嵌套查詢的參數(shù)
fetchType:是否使用懶加載,'lazy'為懶加載,'eager'為積極加載
b.示例代碼
<!--一對(duì)一的嵌套查詢-->
<resultMap id="companyExt" type="com.test.dto.CompanyExt">
<id column="id" property="id"/>
<result column="remark" property="remark"/>
<result column="create_time" property="createTime"/>
</resultMap>
<sql id="companyExtSelectColumns">
`id`,`remark`,`create_time`
</sql>
<select id="getCompanyExtById" resultMap="companyExt">
SELECT
<include refid="companyExtSelectColumns"/>
FROM company_ext WHERE id = #{id,jdbcType=VARCHAR};
</select>
<resultMap id="companyAndExtResultMap" extends="companyResultMap" type="com.test.dto.CompanyAndExt">
<association property="companyExt" fetchType="lazy" column="id" javaType="com.test.dto.CompanyExt"
select="com.test.mapper.CompanyMapper.getCompanyExtById"/>
</resultMap>
<select id="getCompanyAndExtById" resultMap="companyAndExtResultMap">
SELECT
<include refid="selectColumns"/>
FROM company c WHERE c.id = #{id,jdbcType=INTEGER}
</select>
補(bǔ)充說明:
column屬性:column="id",表示查詢結(jié)果與嵌套方法入?yún)⒚Q相同,且入?yún)⒅挥幸粋€(gè)。多個(gè)參數(shù)使用column="{resultId=id,resultCode=code}",resultId、resultCode都為主查詢的結(jié)果名
fetchType屬性:fetchType="lazy" 表示使用懶加載,即程序中實(shí)際使用了CompanyAndExt.CompanyExt里的屬性或方法,才進(jìn)行查詢,這樣會(huì)大大增加查詢效率。
一對(duì)多(collection)
collection支持的屬性及其屬性的作用于association完全相同(詳情可見上文)
- 嵌套結(jié)果
a. myBatis中的javaType與ofType的區(qū)別
都是用于指定對(duì)象類型,javaType是用來指定映射pojo中的屬性的類型,而ofType是用來指定映射至集合中的pojo類型。
b. 示例源碼
<!--一對(duì)多的嵌套結(jié)果-->
<resultMap id="companyResultMap" type="com.test.dto.Company">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="name" column="name"/>
<result property="source" column="source"/>
<result property="createTime" column="create_time"/>
</resultMap>
<resultMap id="companyPriceResultMap" extends="companyResultMap" type="com.test.dto.CompanyPrice">
<collection property="stockPriceList" ofType="com.test.dto.StockPrice" columnPrefix="cp_">
<id column="id" property="id"/>
<result column="company_id" property="companyId"/>
<result column="date" property="date"/>
<result column="price" property="price"/>
<result column="create_time" property="createTime"/>
</collection>
</resultMap>
<select id="getCompanyPriceById" resultMap="companyPriceResultMap">
SELECT
c.`id`,
c.`name`,
c.`code`,
c.`source`,
c.`create_time`,
cp.`id` AS cp_id,
cp.`company_id` AS cp_company_id,
cp.`date` AS cp_date,
cp.`price` AS cp_price,
cp.`create_time` AS cp_create_time
FROM
company AS c ,
company_price AS cp
WHERE
c.`id` = cp.`company_id` AND
c.`id` = #{id,jdbcType=VARCHAR};
</select>
- 嵌套查詢
a. 示例源碼
<!--一對(duì)多的嵌套查詢-->
<resultMap id="stockPriceResultMap" type="com.test.dto.StockPrice">
<id column="id" property="id"/>
<result column="company_id" property="companyId"/>
<result column="date" property="date"/>
<result column="price" property="price"/>
<result column="create_time" property="createTime"/>
</resultMap>
<select id="listStockPriceByCompanyId" resultMap="stockPriceResultMap">
SELECT
cp.`id`,
cp.`company_id`,
cp.`date`,
cp.`price`,
cp.`create_time`
FROM
company_price AS cp
WHERE
cp.company_id = #{companyId,jdbcType=VARCHAR}
</select>
<resultMap id="companyPriceResultMap" extends="companyResultMap" type="com.test.dto.CompanyPrice">
<collection property="stockPriceList" column="id" fetchType="lazy"
select="com.test.mapper.CompanyMapper.listStockPriceByCompanyId"/>
</resultMap>
<select id="getCompanyPriceById" resultMap="companyPriceResultMap">
SELECT
<include refid="selectColumns"/>
FROM company c WHERE c.id = #{id,jdbcType=VARCHAR}
</select>
鑒別器映射(discriminator)
鑒別器非常的容易理解,因?yàn)?,它非常像java中的switch語句
我們直接來看示例代碼,然后根據(jù)示例代碼進(jìn)行講解
<resultMap id="companyPriceResultMap1" type="com.test.dto.CompanyPrice">
......
</resultMap>
<resultMap id="companyPriceResultMap2" type="com.test.dto.CompanyPrice">
......
</resultMap>
<resultMap id="companyPriceResultMap" type="com.test.dto.CompanyPrice">
<discriminator javaType="int" column="code">
<case value="1" resultMap="companyPriceResultMap1" />
<case value="2" resultMap="companyPriceResultMap2" />
</discriminator>
</resultMap>
說明:
- discriminator標(biāo)簽有兩個(gè)屬性:
a. column:需要鑒別的列
b. javaType:指定列的數(shù)據(jù)類型,用于比較 - discriminator的子標(biāo)簽case有三個(gè)屬性
a. value:鑒別的值
b. resultMap:當(dāng)鑒別值匹配時(shí),使用該resultMap指定的映射,resultMap優(yōu)先級(jí)高于resultType
c. resultType:當(dāng)鑒別值匹配時(shí),使用該resultType指定的映射
特別說明:
- 本博客為自己的學(xué)習(xí)筆記,因此存在知識(shí)點(diǎn)覆蓋不全,部分功能遺漏,后續(xù)逐步補(bǔ)充;
- 文中如果存在錯(cuò)誤的地方,還請(qǐng)留言指出,我會(huì)第一時(shí)間糾正;
- 如果有什么不滿(需要補(bǔ)充的知識(shí)點(diǎn)、優(yōu)化點(diǎn)等),還請(qǐng)不吝指教,我會(huì)盡快響應(yīng)處理,謝謝!