元素中,包含了一個 更新時間:2021-06-24 來源:黑馬程序員 瀏覽量: 圖1 人與身份證的關聯(lián)關系 那么使用MyBatis是怎么處理圖1中的這種一對一關聯(lián)關系的呢?在<resultMap>元素中,包含了一個<association>子元素,MyBatis就是通過該元素來處理一對一關聯(lián)關系的。 在<association>元素中,通常可以配置以下屬性: ● property:指定映射到的實體類對象屬性,與表字段一一對應; ● column:指定表中對應的字段; ● javaType:指定映射到實體對象屬性的類型; ● select:指定引入嵌套查詢的子SQL語句,該屬性用于關聯(lián)映射中的嵌套查詢; ● fetchType:指定在關聯(lián)查詢時是否啟用延遲加載。fetchType屬性有l(wèi)azy和eager兩個屬性值,默認值為lazy(即默認關聯(lián)映射延遲加載)。 <association>元素的使用非常簡單,只需要參考如下兩種示例配置即可,具體如下: MyBatis在映射文件中加載關聯(lián)關系對象主要通過兩種方式:嵌套查詢和嵌套結果。嵌套查詢是指通過執(zhí)行另外一條SQL映射語句來返回預期的復雜類型;嵌套結果是使用嵌套結果映射來處理重復的聯(lián)合結果的子集。開發(fā)人員可以使用上述任意一種方式實現(xiàn)對關聯(lián)關系的加載。 了解了MyBatis中處理一對一關聯(lián)關系的元素和方式后,接下來就以個人和身份證之間的一對一關聯(lián)關系為例,進行詳細講解。 查詢個人及其關聯(lián)的身份證信息是先通過查詢個人表中的主鍵來獲個人信息,然后通過表中的外鍵,來獲取證件表中的身份證號信息。其具體實現(xiàn)步驟如下: (1)創(chuàng)建數(shù)據(jù)表。在mybatis數(shù)據(jù)庫中分別創(chuàng)建名為tb_idcard和tb_person的數(shù)據(jù)表,同時預先插入兩條數(shù)據(jù)。其執(zhí)行的SQL語句如下所示: 完成上述操作后,數(shù)據(jù)庫tb_idcard和tb_person表中的數(shù)據(jù)如圖2所示。 圖2 tb_idcard和tb_person表 (2)在Eclipse中創(chuàng)建一個名為chapter09的Web項目,然后引入相關JAR包、log4j日志文件、MybatisUtils工具類以及mybatis-config.xml核心配置文件。項目環(huán)境搭建完成后的文件結構,如圖3所示。 圖3 項目文件結構 (3)在項目的com.itheima.po包下創(chuàng)建持久化類IdCard和Person,編輯后的代碼,如文件1和文件2所示。 文件1 IdCard.java 在上述兩個文件中,分別定義了各自的屬性以及對應的getter/setter方法,同時為了方便查看輸出結果還重寫了toString()方法。 (4)在com.itheima.mapper包中,創(chuàng)建證件映射文件IdCardMapper.xml和個人映射文件PersonMapper.xml,并在兩個映射文件中編寫一對一關聯(lián)映射查詢的配置信息,如文件3和文件4所示。 文件3 IdCardMapper.xml 在上述兩個映射文件中,使用了MyBatis中的嵌套查詢方式進行了個人及其關聯(lián)的證件信息查詢,因為返回的個人對象中除了基本屬性外還有一個關聯(lián)的card屬性,所以需要手動編寫結果映射。從映射文件PersonMapper.xml中可以看出,嵌套查詢的方法是先執(zhí)行一個簡單的SQL語句,然后在進行結果映射時,將關聯(lián)對象在<association>元素中使用select屬性執(zhí)行另一條SQL語句(即IdCardMapper.xml中的SQL)。 (5)在核心配置文件mybatis-config.xml中,引入Mapper映射文件并定義別名,如文件5所示。 文件5 mybatis-config.xml 在上述核心配置文件中,首先引入了數(shù)據(jù)庫連接的配置文件,然后使用掃描包的形式自定義別名,接下來進行環(huán)境的配置,最后配置了Mapper映射文件的位置信息。 (6)在com.itheima.test包中,創(chuàng)建測試類MybatisAssociatedTest,并在類中編寫測試方法findPersonByIdTest(),如文件6所示。 文件6 MybatisAssociatedTest.java 在文件6的findPersonByIdTest()方法中,首先通過MybatisUtils工具類獲取了SqlSession對象,然后通過SqlSession對象的selectOne()方法獲取了個人信息。為了查看結果,這里使用了輸出語句輸出查詢結果信息。最后程序執(zhí)行完畢時,關閉了SqlSession。 使用JUnit4執(zhí)行findPersonByIdTest()方法后,控制臺的輸出結果如圖4所示。 圖4 運行結果 從圖4可以看出,使用MyBatis嵌套查詢的方式查詢出了個人及其關聯(lián)的身份證信息,這就是MyBatis中的一對一關聯(lián)查詢。 雖然使用嵌套查詢的方式比較簡單,但是從圖4中可以看出,MyBatis嵌套查詢的方式要執(zhí)行多條SQL語句,這對于大型數(shù)據(jù)集合和列表展示不是很好,因為這樣可能會導致成百上千條關聯(lián)的SQL語句被執(zhí)行,從而極大的消耗數(shù)據(jù)庫性能并且會降低查詢效率。這并不是開發(fā)人員所期望的。為此,我們可以使用MyBatis提供的嵌套結果方式,來進行關聯(lián)查詢。 在PersonMapper.xml中,使用MyBatis嵌套結果的方式進行個人及其關聯(lián)的證件信息查詢,所添加的代碼如下所示: 從上述代碼中可以看出,MyBatis嵌套結果的方式只編寫了一條復雜的多表關聯(lián)的SQL語句,并且在<association>元素中繼續(xù)使用相關子元素進行數(shù)據(jù)庫表字段和實體類屬性的一一映射。 在測試類MybatisAssociatedTest中,編寫測試方法findPersonByIdTest2(),其代碼如下所示。 使用JUnit4執(zhí)行findPersonByIdTest2()方法后,控制臺的輸出結果如圖5所示。 圖5 運行結果 從圖5可以看出,使用MyBatis嵌套結果的方式只執(zhí)行了一條SQL語句,并且同樣查詢出了個人及其關聯(lián)的身份證的信息。 MyBatis延遲加載的配置: 在使用MyBatis嵌套查詢方式進行MyBatis關聯(lián)查詢映射時,使用MyBatis的延遲加載在一定程度上可以降低運行消耗并提高查詢效率。MyBatis默認沒有開啟延遲加載,需要在核心配置文件mybatis-config.xml中的<settings>元素內進行配置,具體配置方式如下: 在映射文件中,MyBatis關聯(lián)映射的<association>元素和<collection>元素中都已默認配置了延遲加載屬性,即默認屬性fetchType="lazy"(屬性fetchType="eager"表示立即加載),所以在配置文件中開啟延遲加載后,無需在映射文件中再做配置。MyBatis怎樣處理一對一關聯(lián)關系?
<!--方式一:嵌套查詢-->
<association property="card" column="card_id"
javaType="com.itheima.po.IdCard"
select="com.itheima.mapper.IdCardMapper.findCodeById" />
<!--方式二:嵌套結果-->
<association property="card" javaType="com.itheima.po.IdCard">
<id property="id" column="card_id" />
<result property="code" column="code" />
</association>
注意:USE mybatis;
# 創(chuàng)建一個名稱為tb_idcard的表
CREATE TABLE tb_idcard(
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(18)
);
# 插入2條數(shù)據(jù)
INSERT INTO tb_idcard(CODE) VALUES('152221198711020624');
INSERT INTO tb_idcard(CODE) VALUES('152201199008150317');
# 創(chuàng)建一個名稱為tb_person的表
CREATE TABLE tb_person(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32),
age INT,
sex VARCHAR(8),
card_id INT UNIQUE,
FOREIGN KEY(card_id) REFERENCES tb_idcard(id)
);
# 插入2條數(shù)據(jù)
INSERT INTO tb_person(name,age,sex,card_id) VALUES('Rose',29,'女',1);
INSERT INTO tb_person(name,age,sex,card_id) VALUES('tom',27,'男',2);
package com.itheima.po;
/**
* 證件持久化類
*/
public class IdCard {
private Integer id;
private String code;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return "IdCard [id=" + id + ", code=" + code + "]";
}
}
文件2 Person.java package com.itheima.po;
/**
* 個人持久化類
*/
public class Person {
private Integer id;
private String name;
private Integer age;
private String sex;
private IdCard card; //個人關聯(lián)的證件
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public IdCard getCard() {
return card;
}
public void setCard(IdCard card) {
this.card = card;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", "
+ "age=" + age + ", sex=" + sex + ", card=" + card + "]";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.IdCardMapper">
<!-- 根據(jù)id查詢證件信息 -->
<select id="findCodeById" parameterType="Integer" resultType="IdCard">
SELECT * from tb_idcard where id=#{id}
</select>
</mapper>
文件4 PersonMapper.xml <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.PersonMapper">
<!-- 嵌套查詢:通過執(zhí)行另外一條SQL映射語句來返回預期的特殊類型 -->
<select id="findPersonById" parameterType="Integer"
resultMap="IdCardWithPersonResult">
SELECT * from tb_person where id=#{id}
</select>
<resultMap type="Person" id="IdCardWithPersonResult">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<!-- 一對一:association使用select屬性引入另外一條SQL語句 -->
<association property="card" column="card_id" javaType="IdCard"
select="com.itheima.mapper.IdCardMapper.findCodeById" />
</resultMap>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入數(shù)據(jù)庫連接配置文件 -->
<properties resource="db.properties" />
<!--使用掃描包的形式定義別名 -->
<typeAliases>
<package name="com.itheima.po" />
</typeAliases>
<!--配置環(huán)境 ,默認的環(huán)境id為mysql -->
<environments default="mysql">
<!-- 配置id為mysql的數(shù)據(jù)庫環(huán)境 -->
<environment id="mysql">
<!-- 使用JDBC的事務管理 -->
<transactionManager type="JDBC" />
<!--數(shù)據(jù)庫連接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!--配置Mapper的位置 -->
<mappers>
<mapper resource="com/itheima/mapper/IdCardMapper.xml" />
<mapper resource="com/itheima/mapper/PersonMapper.xml" />
</mappers>
</configuration>
package com.itheima.test;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.itheima.po.Person;
import com.itheima.utils.MybatisUtils;
/**
* Mybatis關聯(lián)查詢映射測試類
*/
public class MybatisAssociatedTest {
/**
* 嵌套查詢
*/
@Test
public void findPersonByIdTest() {
// 1、通過工具類生成SqlSession對象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套查詢的方式查詢id為1的人的信息
Person person = session.selectOne("com.itheima.mapper."
+ "PersonMapper.findPersonById", 1);
// 3、輸出查詢結果信息
System.out.println(person);
// 4、關閉SqlSession
session.close();
}
}
<!-- 嵌套結果:使用嵌套結果映射來處理重復的聯(lián)合結果的子集 -->
<select id="findPersonById2" parameterType="Integer"
resultMap="IdCardWithPersonResult2">
SELECT p.*,idcard.code
from tb_person p,tb_idcard idcard
where p.card_id=idcard.id
and p.id= #{id}
</select>
<resultMap type="Person" id="IdCardWithPersonResult2">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<association property="card" javaType="IdCard">
<id property="id" column="card_id" />
<result property="code" column="code" />
</association>
</resultMap>
/**
* 嵌套結果
*/
@Test
public void findPersonByIdTest2() {
// 1、通過工具類生成SqlSession對象
SqlSession session = MybatisUtils.getSession();
// 2.使用MyBatis嵌套結果的方法查詢id為1的人的信息
Person person = session.selectOne("com.itheima.mapper."
+ "PersonMapper.findPersonById2", 1);
// 3、輸出查詢結果信息
System.out.println(person);
// 4、關閉SqlSession
session.close();
}
<settings>
<!-- 打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 將積極加載改為消息加載,即按需加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
猜你喜歡:
最新資訊