MyBatis映射關(guān)系詳解
數(shù)據(jù)庫的配置
CREATE TABLE person ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(32) NOT NULL DEFAULT '', card_id INT , FOREIGN KEY (card_id) REFERENCES idencard(id) )CHARSET utf8;
-- 創(chuàng)建 mybatis_idencard 表 CREATE TABLE idencard ( id INT PRIMARY KEY AUTO_INCREMENT, card_sn VARCHAR(32) NOT NULL DEFAULT '' )CHARSET utf8 ; INSERT INTO idencard VALUES(1,'111111111111110'); INSERT INTO person VALUES(1,'張三',1); SELECT * FROM person; SELECT * FROM idencard
一.映射關(guān)系一對一
1.映射關(guān)系 1 對 1-基本介紹
● 基本介紹
1. 項目中 1 對 1 的關(guān)系是一個基本的映射關(guān)系,比如 :Person( 人 ) --- IDCard( 身份證 )
2. 我們看看再 MyBatis 中如何實現(xiàn) 1 對 1 的處理 .
● 注意細節(jié)
1 對 1 , 我們這里就研究一下單向 1 對 1 即可
2.映射關(guān)系 1 對 1-映射方式
映射方式
1. 通過配置 XxxMapper.xml 實現(xiàn) 1 對 1 [ 配置方式 ]
2. 通過注解的方式實現(xiàn) 1 對 1 [ 注解方式 ]
3.應(yīng)用實例
3.1方式一
通過配置 XxxMapper.xml 的方式來實現(xiàn)下面的 1 對 1 的映射關(guān)系,實現(xiàn) 級
聯(lián)查詢 , 通過 person 可以獲取到對應(yīng)的 idencard 信息

然后建立各自的javabean--->兩個表


然后我們就可以開始重頭戲了開始建立IdenCardMapper.java和IdenCardMapper.xml
public interface IdenCardMapper {
//根據(jù)id獲取到身份證序列號
public IdenCard getIdenCardById(Integer id);
<!--
1、配置/實現(xiàn)//根據(jù)id獲取到身份證序列號
2、public IdenCard getIdenCardById(Integer id);
-->
<select id="getIdenCardById" parameterType="Integer"
resultType="IdenCard">
SELECT * FROM `idencard` WHERE `id` = #{id}
</select> //通過Person的id獲取到Person,包括這個Person關(guān)聯(lián)的IdenCard對象[級聯(lián)查詢]
public Person getPersonById(Integer id);
<mapper namespace="com.hong.mapper.PersonMapper">
<!--
1、配置/實現(xiàn)public Person getPersonById(Integer id);
2、完成通過Person的id獲取到Person,包括這個Person關(guān)聯(lián)的IdenCard對象[級聯(lián)查詢]
3. 為了讓小伙伴們理解的更加深刻一點,先用大家容易想到的方式-分析問題-解決問題
4. 看到如果配置成簡單 resultType="Person" 問題就是沒有實現(xiàn)級聯(lián)查詢
5. 自定義resultMap 搞定 映射返回的結(jié)果
6. 因為 getPersonById 最終返回的是 Person對象[只是有級聯(lián)的對象屬性], type仍然配置"Person"
-->
<resultMap id="PersonResultMap" type="Person">
<!--<result property="id" column="id"/>-->
<!--id – 一個 ID 結(jié)果;標記出作為 ID 的結(jié)果可以幫助提高整體性能
1.property="id" 表示person 屬性 id ,通常是主鍵
2.column="id" 表示對應(yīng)表的字段
-->
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--association – 一個復(fù)雜類型的關(guān)聯(lián)
1. property="card" 表示 Person對象的 card 屬性
2. javaType="IdenCard" 表示card 屬性 的類型
3. column="id" 是從我們的 下面這個語句查詢后返回的字段
SELECT * FROM `person`,`idencard` WHERE `person`.id=1
AND `person`.card_id = `idencard`.id
-->
<association property="card" javaType="IdenCard">
<result property="id" column="id"/>
<result property="card_sn" column="card_sn"/>
</association>
</resultMap>
<select id="getPersonById" parameterType="Integer"
resultMap="PersonResultMap">
SELECT * FROM `person`,`idencard` WHERE `person`.id = #{id}
AND `person`.card_id = `idencard`.id
</select>
</mapper>
方式二: 通過配置 XxxMapper.xml 的方式來實現(xiàn)下面的 1 對 1 的映射關(guān)系,實現(xiàn)級 聯(lián)查詢 , 通過 person 可以獲取到對應(yīng)的 identcard 信息

1. 修改 PersonMapper.java 和 PersonMapper.xml 使用第 2 種映射方式 , 完成 1 對 1 映射 關(guān)系
//通過Person的id獲取到Person,包括這個Person關(guān)聯(lián)的IdenCard對象,方式2
public Person getPersonById2(Integer id);
//編寫方法,通過card_id 查詢得到person對象/數(shù)據(jù)
public Person getPersonByCardId(Integer cardId); <!--
1、通過Person的id獲取到Person,包括這個Person關(guān)聯(lián)的IdenCard對象,方式2
2、public Person getPersonById2(Integer id);
3. 這里的方式和前面不同.
1) 先通過 SELECT * FROM `person` WHERE `id` = #{id} 返回 person信息
2) 再通過 返回的card_id 值,再執(zhí)行操作,得到IdenCard 數(shù)據(jù)
-->
<resultMap id="PersonResultMap2" type="Person">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="card" column="card_id"
select="com.hong.mapper.IdenCardMapper.getIdenCardById" />
</resultMap>
<select id="getPersonById2" parameterType="Integer" resultMap="PersonResultMap2">
SELECT * FROM `person` WHERE `id` = #{id}
</select>
</mapper>1. mybatis第二種方式核心思想: 將這個多表聯(lián)查,分解成單表操作 , 這樣簡潔,而且易于維護 ,推薦
2. 而且可以復(fù)用你已經(jīng)寫好的方法 -組合
3. property="card": 表示 Person對象的 card 屬性
4. column="card_id" 這個是
SELECT * FROM `person` WHERE `id` = #{id} 返回的 字段 card_id 信息/數(shù)據(jù)
5. 返回的 字段 card_id 信息/數(shù)據(jù) 作為getIdenCardById入?yún)? 來執(zhí)行
重點解析:
先執(zhí)行下面的select語句,然后將執(zhí)行的結(jié)果中的card_id傳參給getIdenCardById,這個時候我們就直接返回的就是確定這個值的IdenCard的值了。
好,現(xiàn)在我們試著來說明一下啥叫將多表級聯(lián)變成現(xiàn)在的單表操作。
就是我們先來思考一下MySQL中的多表查詢,是不是有一個子查詢,你要是知道這個就差不多理解了一半了。我們數(shù)據(jù)庫中的子查詢是先將一個查詢結(jié)果返回給另外一個SQL語句進行操作。那么一對一映射其實本質(zhì)也是一樣,我們先將一個結(jié)果作為參數(shù)然后傳入到一個方法中,這個方法就可以運用這個結(jié)果去執(zhí)行他的操作。
注解的方式實現(xiàn) 通過注解的方式來實現(xiàn)下面的 1 對 1 的映射關(guān)系,實現(xiàn)級聯(lián)查詢 , 通過 person 可以獲取到 對應(yīng)的 identcard 信息 在實際開發(fā)中還是 推薦使用配置方式
public interface PersonMapperAnnotation {
//這里注解實現(xiàn)方法
//說明: 注解的形式就是對前面xml配置方式的體現(xiàn)
//這里同學(xué)們可以結(jié)合前面講解的xml配置時,加入的注釋來理解
@Select("SELECT * FROM `person` WHERE `id` = #{id}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "card", column = "card_id",
one = @One(select = "com.hong.mapper.IdenCardMapper.getIdenCardById"))
})
public Person getPersonById(Integer id);
}
注解的方式也就是xml形式的另外一種體現(xiàn)
public class PersonMapperAnnotationTest {
//屬性
private SqlSession sqlSession;
private PersonMapperAnnotation personMapperAnnotation;
//初始化
@Before
public void init() {
//獲取到sqlSession
sqlSession = MyBatisUtils.getSqlSession();
personMapperAnnotation = sqlSession.getMapper(PersonMapperAnnotation.class);
}
@Test
public void getPersonById() {
Person person = personMapperAnnotation.getPersonById(1);
System.out.println("person----" + person);
if(sqlSession != null) {
sqlSession.close();
}
}
}
注意事項和細節(jié)
1. 表是否設(shè)置外鍵 , 對 MyBatis 進行對象 / 級聯(lián)映射沒有影響
2. 舉例 : 去掉 person 表的外鍵 , 進行測試 , 依然可以獲取相應(yīng)的級聯(lián)對象

二.映射關(guān)系多對一
1.基本介紹
1. 項目中多對 1 的關(guān)系是一個基本的映射關(guān)系 , 多對 1, 也可以理解成是 1 對多 .
2. User --- Pet : 一個用戶可以養(yǎng)多只寵物
3. Dep ---Emp : 一個部門可以有多個員工
2.注意細節(jié)
1. 我們直接講 雙向的多對一的關(guān)系 ,單向的多對一比雙向的多對一簡單。
2. 在實際的項目開發(fā)中 , 要求會使用雙向的多對一的映射關(guān)系
3. 說明:什么是 雙向的多對一 的關(guān)系 : 比如通過 User 可以查詢到對應(yīng)的 Pet, 反過 來,通過 Pet 也可以級聯(lián)查詢到對應(yīng)的 User 信息 .
4. 多對多的關(guān)系,是在多對 1 的基礎(chǔ)上擴展即可
3.映射方式
1. 方式 1 :通過配置 XxxMapper.xml 實現(xiàn)多對 1 2.
方式 2 :通過注解的方式實現(xiàn) 多對 1
4.代碼實現(xiàn)
4.1數(shù)據(jù)庫表
CREATE TABLE mybatis_user (id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(32) NOT NULL DEFAULT '' )CHARSET=utf8 ; CREATE TABLE mybatis_pet (id INT PRIMARY KEY AUTO_INCREMENT, nickname VARCHAR(32) NOT NULL DEFAULT '', user_id INT , FOREIGN KEY (user_id) REFERENCES mybatis_user(id) )CHARSET=utf8 ; INSERT INTO mybatis_user VALUES(NULL,'宋江'),(NULL,'張飛'); INSERT INTO mybatis_pet VALUES(1,'黑背',1),(2,'小哈',1); INSERT INTO mybatis_pet VALUES(3,'波斯貓',2),(4,'貴妃貓',2); SELECT * FROM mybatis_user; SELECT * FROM mybatis_pet;

4.2UserMapper.xml文件
<mapper namespace="com.hong.mapper.UserMapper">
<!--解讀
1、一定要想一想我們前面1-1是如何實現(xiàn)
2、配置/實現(xiàn) public User getUserById(Integer id);
3、思路(1) 先通過user-id 查詢得到user信息 (2) 再根據(jù)user-id查詢對應(yīng)的pet信息
并映射到User-List<Pet> pets
-->
<resultMap id="UserResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!--解讀:因為pets屬性是集合,因此這里需要是collection標簽來處理
1. ofType="Pet" 指定返回的集合中存放的數(shù)據(jù)類型Pet
2. collection 表示 pets 是一個集合
3. property="pets" 是返回的user對象的屬性 pets
4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段對應(yīng)的值
-->
<collection property="pets" column="id" ofType="Pet"
select="com.hong.mapper.PetMapper.getPetByUserId"/>
</resultMap>
<select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
SELECT * FROM `mybatis_user` WHERE `id` = #{id}
</select>
</mapper>
4.3PetMapper.xml文件
<mapper namespace="com.hong.mapper.PetMapper">
<!--
1、通過User的id來獲取pet對象,可能有多個,因此使用List接收
2、public List<Pet> getPetByUserId(Integer userId);
3. 完成的思路和前面大體相同.
-->
<resultMap id="PetResultMap" type="Pet">
<id property="id" column="id"/>
<result property="nickname" column="nickname"/>
<association property="user" column="user_id"
select="com.hong.mapper.UserMapper.getUserById" />
</resultMap>
<select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
</select>
<!--說明
1. 注意體會resultMap帶來好處, 直接復(fù)用
2. 實現(xiàn)/配置public Pet getPetById(Integer id);
3. 通過pet的id獲取Pet對象
-->
<select id="getPetById"
parameterType="Integer"
resultMap="PetResultMap">
SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
</select>
</mapper>注解實現(xiàn)多對 1 映射
需求說明 : 通過注解的方式來實現(xiàn)下面的多對 1 的映射關(guān)系,實現(xiàn)級聯(lián)查詢 , 完成前面完成 的任務(wù),通過 User-->Pet 也可 Pet->User , 在實際開發(fā)中 推薦使用配置方式來 做
public interface UserMapperAnnotation {
//通過id獲取User對象
/**
* 1. 注解的配置就是對應(yīng)的Mapper.xml文件配置的,改寫
* 2.
* 1、一定要想一想我們前面1-1是如何實現(xiàn)
* 2、配置/實現(xiàn) public User getUserById(Integer id);
* 3、思路(1) 先通過user-id 查詢得到user信息 (2) 再根據(jù)user-id查詢對應(yīng)的pet信息
* 并映射到User-List<Pet> pets
* <resultMap id="UserResultMap" type="User">
* <id property="id" column="id"/>
* <result property="name" column="name"/>
* 1. ofType="Pet" 指定返回的集合中存放的數(shù)據(jù)類型Pet
* 2. collection 表示 pets 是一個集合
* 3. property="pets" 是返回的user對象的屬性 pets
* 4. column="id" SELECT * FROM `mybatis_user` WHERE `id` = #{id} 返回的id字段對應(yīng)的值
* -->
* <collection property="pets" column="id" ofType="Pet"
* select="com.hong.mapper.PetMapper.getPetByUserId"/>
* </resultMap>
* <select id="getUserById" parameterType="Integer" resultMap="UserResultMap">
* SELECT * FROM `mybatis_user` WHERE `id` = #{id}
* </select>
*/
@Select("SELECT * FROM `mybatis_user` WHERE `id` = #{id}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
//這里請小伙伴注意,pets屬性對應(yīng)的是集合
@Result(property = "pets",
column = "id",
many = @Many(select = "com.hong.mapper.PetMapperAnnotation.getPetByUserId"))
})
public User getUserById(Integer id);
}
public interface PersonMapperAnnotation {
//這里注解實現(xiàn)方法
//說明: 注解的形式就是對前面xml配置方式的體現(xiàn)
//這里同學(xué)們可以結(jié)合前面老師講解的xml配置時,加入的注釋來理解
@Select("SELECT * FROM `person` WHERE `id` = #{id}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "card", column = "card_id",
one = @One(select = "com.hong.mapper.IdenCardMapper.getIdenCardById"))
})
public Person getPersonById(Integer id);
}
public interface PetMapperAnnotation {
//通過User的id來獲取pet對象,可能有多個,因此使用List接收
/**
* 1、通過User的id來獲取pet對象,可能有多個,因此使用List接收
* 2、public List<Pet> getPetByUserId(Integer userId);
* 3. 完成的思路和前面大體相同.
* <resultMap id="PetResultMap" type="Pet">
* <id property="id" column="id"/>
* <result property="nickname" column="nickname"/>
* <association property="user" column="user_id"
* select="com.hong.mapper.UserMapper.getUserById" />
* </resultMap>
* <select id="getPetByUserId" parameterType="Integer" resultMap="PetResultMap">
* SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}
* </select>
*/
//id = "PetResultMap" 就是給我們的Results[Result Map] 指定一個名字
//,目的是為了后面復(fù)用
@Select("SELECT * FROM `mybatis_pet` WHERE `user_id` = #{userId}")
@Results(id = "PetResultMap", value = {
@Result(id = true, property = "id", column = "id"),
@Result(property = "nickname", column = "nickname"),
@Result(property = "user",
column = "user_id",
one = @One(select = "com.hong.mapper.UserMapperAnnotation.getUserById"))
})
public List<Pet> getPetByUserId(Integer userId);
//通過pet的id獲取Pet對象, 同時會查詢到pet對象關(guān)聯(lián)的user對象
/**
* <select id="getPetById"
* parameterType="Integer"
* resultMap="PetResultMap">
* SELECT * FROM `mybatis_pet` WHERE `id` = #{id}
* </select>
*
* @ResultMap("PetResultMap") 使用/引用我們上面定義的 Results[ResultMap]
*/
@Select("SELECT * FROM `mybatis_pet` WHERE `id` = #{id}")
@ResultMap("PetResultMap")
public Pet getPetById(Integer id);
}
?一對多的思路:
1.首先我們通過id="getUserById"的select查詢獲取到user-id對應(yīng)的所有數(shù)據(jù)
2.之后也可以通過user-id獲取到pet是的信息
3.之后我們也可以通過User的id來獲取pet對象,可能有多個,因此使用List接收
?
簡而言之:
就是我們可以通過主人的id查詢到寵物的信息,同時也可以通過寵物的信息查詢到主人。
一對一是我先查詢一個id,在通過這個id查詢到一個信息,而這個信息是可以查詢到另外一個表的信息的。而一對多是我通過一個字段查詢到這個字段在這個信息里面的所相關(guān)的內(nèi)容(就像一個id可以查詢到主人對應(yīng)的寵物信息),當(dāng)然是存放在集合之中的。
到此這篇關(guān)于MyBatis映射關(guān)系的文章就介紹到這了,更多相關(guān)MyBatis映射關(guān)系內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring mvc實現(xiàn)文件上傳并攜帶其他參數(shù)的示例
本篇文章主要介紹了spring mvc實現(xiàn)文件上傳并攜帶其他參數(shù)的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
SpringMVC獲取請求參數(shù)和域?qū)ο蠊蚕頂?shù)據(jù)的示例代碼
這篇文章主要給大家介紹了SpringMVC獲取請求參數(shù)和域?qū)ο蠊蚕頂?shù)據(jù)的示例代碼,文中通過代碼示例給大家介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下2023-12-12
SpringBoot集成ElaticJob定時器的實現(xiàn)代碼
這篇文章主要介紹了SpringBoot集成ElaticJob定時器的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
Spring Cloud體系實現(xiàn)標簽路由的方法示例
這篇文章主要介紹了Spring Cloud體系實現(xiàn)標簽路由的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05
springboot配置Jackson返回統(tǒng)一默認值的實現(xiàn)示例
在項目開發(fā)中,我們返回的數(shù)據(jù)或者對象沒有的時候一般直接返回的null,那么如何返回統(tǒng)一默認值,感興趣的可以了解一下2021-07-07

