自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:請(qǐng)講一下MyBatis是如何關(guān)聯(lián)關(guān)系?

開發(fā) 前端
實(shí)際的開發(fā)中,對(duì)數(shù)據(jù)庫的操作常常會(huì)涉及到多張表,這在面向?qū)ο笾芯蜕婕暗搅藢?duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。針對(duì)多表之間的操作,MyBatis提供了關(guān)聯(lián)映射,通過關(guān)聯(lián)映射就可以很好的處理對(duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。

[[433880]]

文末本文轉(zhuǎn)載自微信公眾號(hào)「程序員千羽」,作者程序員千羽。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序員千羽公眾號(hào)。

“GitHub:https://github.com/nateshao/ssm/tree/master/115-mybatis-associated-one-many

1. 關(guān)聯(lián)關(guān)系概述

為什么學(xué)習(xí)MyBatis關(guān)聯(lián)關(guān)系?

“實(shí)際的開發(fā)中,對(duì)數(shù)據(jù)庫的操作常常會(huì)涉及到多張表,這在面向?qū)ο笾芯蜕婕暗搅藢?duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。針對(duì)多表之間的操作,MyBatis提供了關(guān)聯(lián)映射,通過關(guān)聯(lián)映射就可以很好的處理對(duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。所以,,這里將對(duì)MyBatis的關(guān)聯(lián)關(guān)系映射進(jìn)行詳細(xì)的講解。

在關(guān)系型數(shù)據(jù)庫中,多表之間存在著三種關(guān)聯(lián)關(guān)系,分別為一對(duì)一、一對(duì)多和多對(duì)多,如下圖所示:

一對(duì)一:在任意一方引入對(duì)方主鍵作為外鍵;

一對(duì)多:在“多”的一方,添加“一”的一方的主鍵作為外鍵;

多對(duì)多:產(chǎn)生中間關(guān)系表,引入兩張表的主鍵作為外鍵,兩個(gè)主鍵成為聯(lián)合主鍵或使用新的字段作為主鍵。

在Java中,通過對(duì)象也可以進(jìn)行關(guān)聯(lián)關(guān)系描述,如圖下圖所示:

2. 一對(duì)一

在現(xiàn)實(shí)生活中,一對(duì)一關(guān)聯(lián)關(guān)系是十分常見的。例如,一個(gè)人只能有一個(gè)身份證,同時(shí)一個(gè)身份證也只會(huì)對(duì)應(yīng)一個(gè)人。

那么使用MyBatis是怎么處理圖中的這種一對(duì)一關(guān)聯(lián)關(guān)系的呢?

在前面所講解的< resultMap >元素中,包含了一個(gè)< association >子元素,MyBatis就是通過該元素來處理一對(duì)一關(guān)聯(lián)關(guān)系的。

在< association >元素中,通常可以配置以下屬性:

property:指定映射到的實(shí)體類對(duì)象屬性,與表字段一 一對(duì)應(yīng)

column:指定表中對(duì)應(yīng)的字段

javaType:指定映射到實(shí)體對(duì)象屬性的類型

select:指定引入嵌套查詢的子SQL語句,該屬性用于關(guān)聯(lián)映射中的嵌套查詢

fetchType:指定在關(guān)聯(lián)查詢時(shí)是否啟用延遲加載。該屬性有l(wèi)azy和eager兩個(gè)屬性值,默認(rèn)值為lazy(即默認(rèn)關(guān)聯(lián)映射延遲加載)

MyBatis加載關(guān)聯(lián)關(guān)系對(duì)象主要通過兩種方式:嵌套查詢和嵌套結(jié)果。

第一種: 嵌套查詢是通過執(zhí)行另外一條SQL映射語句來返回預(yù)期的復(fù)雜類型。

  • 嵌套查詢是在查詢SQL中嵌入一個(gè)子查詢SQL;
  • 嵌套查詢會(huì)執(zhí)行多條SQL語句;
  • 嵌套查詢SQL語句編寫較為簡(jiǎn)單;

第二種: 嵌套結(jié)果是使用嵌套結(jié)果映射來處理重復(fù)的聯(lián)合結(jié)果的子集。

  • 嵌套結(jié)果是一個(gè)嵌套的多表查詢SQL;
  • 嵌套結(jié)果只會(huì)執(zhí)行一條復(fù)雜的SQL語句;
  • 嵌套結(jié)果SQL語句編寫比較復(fù)雜;

“雖然使用嵌套查詢的方式比較簡(jiǎn)單,但是嵌套查詢的方式要執(zhí)行多條SQL語句,這對(duì)于大型數(shù)據(jù)集合和列表展示不是很好,因?yàn)檫@樣可能會(huì)導(dǎo)致成百上千條關(guān)聯(lián)的SQL語句被執(zhí)行,從而極大的消耗數(shù)據(jù)庫性能并且會(huì)降低查詢效率。

多學(xué)一招:MyBatis延遲加載的配置

使用MyBatis的延遲加載在一定程度上可以降低運(yùn)行消耗并提高查詢效率。MyBatis默認(rèn)沒有開啟延遲加載,需要在核心配置文件中的< settings >元素內(nèi)進(jìn)行配置,具體配置方式如下:

  1. <settings> 
  2.           <setting name="lazyLoadingEnabled" value="true" />   
  3.           <setting name="aggressiveLazyLoading" value="false"/>   
  4.   </settings> 

在映射文件中,< association > 元素和< collection > 元素中都已默認(rèn)配置了延遲加載屬性,即默認(rèn)屬性fetchType="lazy"(屬性fetchType="eager"表示立即加載),所以在配置文件中開啟延遲加載后,無需在映射文件中再做配置。

使用< association >元素進(jìn)行一對(duì)一關(guān)聯(lián)映射非常簡(jiǎn)單,只需要參考如下兩種示例配置即可。

代碼實(shí)現(xiàn):

  1. 第一種: 
  2. <!-- 嵌套查詢:通過執(zhí)行另外一條SQL映射語句來返回預(yù)期的特殊類型 --> 
  3.     <select id="findPersonById" parameterType="Integer" 
  4.             resultMap="IdCardWithPersonResult"
  5.   SELECT * from tb_person where id=#{id} 
  6.  </select
  7.     <resultMap type="Person" id="IdCardWithPersonResult"
  8.         <id property="id" column="id"/> 
  9.         <result property="name" column="name"/> 
  10.         <result property="age" column="age"/> 
  11.         <result property="sex" column="sex"/> 
  12.         <!-- 一對(duì)一:association使用select屬性引入另外一條SQL語句 --> 
  13.         <association property="card" column="card_id" javaType="IdCard" 
  14.                      select="com.nateshao.mapper.IdCardMapper.findCodeById"/> 
  15.     </resultMap> 
  16. 第二種: 
  17.     <!-- 嵌套結(jié)果:使用嵌套結(jié)果映射來處理重復(fù)的聯(lián)合結(jié)果的子集 --> 
  18.     <select id="findPersonById2" parameterType="Integer" 
  19.             resultMap="IdCardWithPersonResult2"
  20.      SELECT p.*,idcard.code 
  21.      from tb_person p,tb_idcard idcard 
  22.      where p.card_id=idcard.id  
  23.      and p.id= #{id} 
  24.  </select
  25.     <resultMap type="Person" id="IdCardWithPersonResult2"
  26.         <id property="id" column="id"/> 
  27.         <result property="name" column="name"/> 
  28.         <result property="age" column="age"/> 
  29.         <result property="sex" column="sex"/> 
  30.         <association property="card" javaType="IdCard"
  31.             <id property="id" column="card_id"/> 
  32.             <result property="code" column="code"/> 
  33.         </association> 
  34.     </resultMap> 

Person.java

  1. @Data 
  2. public class Person { 
  3.     private Integer id; 
  4.     private String name
  5.     private Integer age; 
  6.     private String sex; 
  7.     private IdCard card;  //個(gè)人關(guān)聯(lián)的證件 

IdCard.java

  1. @Data 
  2. public class IdCard { 
  3.     private Integer id; 
  4.     private String code; 

3. 一對(duì)多

開發(fā)人員接觸更多的關(guān)聯(lián)關(guān)系是一對(duì)多(或多對(duì)一)。例如,一個(gè)用戶可以有多個(gè)訂單,同時(shí)多個(gè)訂單歸一個(gè)用戶所有。

那么使用MyBatis是怎么處理這種一對(duì)多關(guān)聯(lián)關(guān)系的呢?

在前面所講解的< resultMap >元素中,包含了一個(gè)< collection >子元素,MyBatis就是通過該元素來處理一對(duì)多關(guān)聯(lián)關(guān)系的。

< collection >子元素的屬性大部分與< association>元素相同,但其還包含一個(gè)特殊屬性--ofType 。

ofType:ofType屬性與javaType屬性對(duì)應(yīng),它用于指定實(shí)體對(duì)象中集合類屬性所包含的元素類型。

代碼實(shí)現(xiàn):

  1. /** 
  2.  * 一對(duì)多 
  3.  */ 
  4. @Test 
  5. public void findUserTest() { 
  6.     // 1、通過工具類生成SqlSession對(duì)象 
  7.     SqlSession session = MybatisUtils.getSession(); 
  8.     // 2、查詢id為1的用戶信息 
  9.     User user = session.selectOne("com.nateshao.mapper." 
  10.             + "UserMapper.findUserWithOrders", 1); 
  11.     // 3、輸出查詢結(jié)果信息 
  12.     System.out.println(user); 
  13.     // 4、關(guān)閉SqlSession 
  14.     session.close(); 

UserMapper.xml

  1. <!-- 一對(duì)多:查看某一用戶及其關(guān)聯(lián)的訂單信息  
  2.       注意:當(dāng)關(guān)聯(lián)查詢出的列名相同,則需要使用別名區(qū)分 --> 
  3. <select id="findUserWithOrders" parameterType="Integer"  
  4.                   resultMap="UserWithOrdersResult"
  5.    SELECT u.*,o.id as orders_id,o.number  
  6.    from tb_user u,tb_orders o  
  7.    WHERE u.id=o.user_id  
  8.         and u.id=#{id} 
  9. </select
  10. <resultMap type="User" id="UserWithOrdersResult"
  11.    <id property="id" column="id"/> 
  12.    <result property="username" column="username"/> 
  13.    <result property="address" column="address"/> 
  14.    <!-- 一對(duì)多關(guān)聯(lián)映射:collection  
  15.       ofType表示屬性集合中元素的類型,List<Orders>屬性即Orders類 --> 
  16.    <collection property="ordersList" ofType="Orders"
  17.       <id property="id" column="orders_id"/> 
  18.       <result property="number" column="number"/> 
  19.    </collection> 
  20. </resultMap> 

User.java

  1. @Data 
  2. public class User { 
  3.     private Integer id;                 // 用戶編號(hào) 
  4.     private String username;           // 用戶姓名 
  5.     private String address;            // 用戶地址 
  6.     private List<Orders> ordersList; //用戶關(guān)聯(lián)的訂單 

Orders.java

  1. @Data 
  2. public class Orders { 
  3.     private Integer id;    //訂單id 
  4.     private String number;//訂單編號(hào) 
  5.     //關(guān)聯(lián)商品集合信息 
  6.     private List<Product> productList; 
  7.  

運(yùn)行結(jié)果:

  1. User(id=1, username=詹姆斯, address=克利夫蘭, ordersList=[Orders(id=1, number=1000011, productList=null), Orders(id=2, number=1000012, productList=null)]) 

4. 多對(duì)多

在實(shí)際項(xiàng)目開發(fā)中,多對(duì)多的關(guān)聯(lián)關(guān)系也是非常常見的。以訂單和商品為例,一個(gè)訂單可以包含多種商品,而一種商品又可以屬于多個(gè)訂單。

在數(shù)據(jù)庫中,多對(duì)多的關(guān)聯(lián)關(guān)系通常使用一個(gè)中間表來維護(hù),中間表中的訂單id作為外鍵參照訂單表的id,商品id作為外鍵參照商品表的id。

在MyBatis中,多對(duì)多的關(guān)聯(lián)關(guān)系查詢,同樣可以使用前面介紹的< collection >元素進(jìn)行處理(其用法和一對(duì)多關(guān)聯(lián)關(guān)系查詢語句用法基本相同)。

MybatisAssociatedTest.java

  1. /** 
  2.  * 多對(duì)多 
  3.  */ 
  4. @Test 
  5. public void findOrdersTest() { 
  6.     // 1、通過工具類生成SqlSession對(duì)象 
  7.     SqlSession session = MybatisUtils.getSession(); 
  8.     // 2、查詢id為1的訂單中的商品信息 
  9.     Orders orders = session.selectOne("com.nateshao.mapper." 
  10.             + "OrdersMapper.findOrdersWithPorduct", 1); 
  11.     // 3、輸出查詢結(jié)果信息 
  12.     System.out.println(orders); 
  13.     // 4、關(guān)閉SqlSession 
  14.     session.close(); 

OrdersMapper.xml

  1. <!-- 多對(duì)多嵌套結(jié)果查詢:查詢某訂單及其關(guān)聯(lián)的商品詳情 --> 
  2. <select id="findOrdersWithPorduct2" parameterType="Integer" 
  3.            resultMap="OrdersWithPorductResult2"
  4.     select o.*,p.id as pid,p.name,p.price from tb_orders o,tb_product p,tb_ordersitem  oi WHERE oi.orders_id=o.id and oi.product_id=p.id and o.id=#{id} 
  5. </select
  6.    <!-- 自定義手動(dòng)映射類型 --> 
  7.    <resultMap type="Orders" id="OrdersWithPorductResult2"
  8.        <id property="id" column="id"/> 
  9.        <result property="number" column="number"/> 
  10.        <!-- 多對(duì)多關(guān)聯(lián)映射:collection --> 
  11.        <collection property="productList" ofType="Product"
  12.            <id property="id" column="pid"/> 
  13.            <result property="name" column="name"/> 
  14.            <result property="price" column="price"/> 
  15.        </collection> 
  16.    </resultMap> 

Orders.java

  1. @Data 
  2. public class Orders { 
  3.     private Integer id;    //訂單id 
  4.     private String number;//訂單編號(hào) 
  5.     //關(guān)聯(lián)商品集合信息 
  6.     private List<Product> productList; 

Product.java

  1. @Data 
  2. public class Product { 
  3.     private Integer id;  //商品id 
  4.     private String name; //商品名稱 
  5.     private Double price;//商品單價(jià) 
  6.     private List<Orders> orders; //與訂單的關(guān)聯(lián)屬性 

總結(jié):

這篇文章首先對(duì)開發(fā)中涉及到的數(shù)據(jù)表之間以及對(duì)象之間的關(guān)聯(lián)關(guān)系作了簡(jiǎn)要介紹,并由此引出了MyBatis框架中對(duì)關(guān)聯(lián)關(guān)系的處理;

然后通過案例對(duì)MyBatis框架處理實(shí)體對(duì)象之間的三種關(guān)聯(lián)關(guān)系進(jìn)行了詳細(xì)講解。 

通過本章的學(xué)習(xí),我們可以了解數(shù)據(jù)表以及對(duì)象中所涉及到的三種關(guān)聯(lián)關(guān)系,并能夠使用MyBatis框架對(duì)三種關(guān)聯(lián)關(guān)系的查詢進(jìn)行處理。MyBatis中的關(guān)聯(lián)查詢操作在實(shí)際開發(fā)中非常普遍,熟練掌握這三種關(guān)聯(lián)查詢方式有助于提高項(xiàng)目的開發(fā)效率。

 

責(zé)任編輯:武曉燕 來源: 程序員千羽
相關(guān)推薦

2023-09-12 14:56:13

MyBatis緩存機(jī)制

2025-03-10 07:05:07

2021-07-28 10:08:19

類加載代碼塊面試

2023-03-08 07:46:53

面試官優(yōu)化結(jié)構(gòu)體

2022-06-06 15:33:20

線程Java釋放鎖

2023-02-08 08:32:41

輪詢鎖

2023-02-18 13:34:14

Nacos健康檢查機(jī)制

2021-08-28 09:06:11

Dubbo架構(gòu)服務(wù)

2022-06-07 12:03:33

Java內(nèi)存模型

2021-06-02 11:25:18

線程池Java代碼

2024-02-21 16:42:00

2020-07-30 07:58:36

加密算法

2024-02-27 15:23:48

RedLock算法Redis

2023-12-29 13:45:00

2024-01-29 10:08:11

零拷貝Zero-copyCPU 拷貝

2023-01-30 15:39:40

GETHTTP

2023-02-09 08:48:47

Java虛擬機(jī)

2021-08-13 07:23:15

架構(gòu)秒殺系統(tǒng)

2021-11-27 08:13:13

Final 面試

2025-02-27 00:08:24

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)