元素中,包含了一個(gè)子元素,MyBatis就是通過該元素來處理一對(duì)一關(guān)聯(lián)關(guān)系的。"/> 亚洲国产无码,向日葵视频下载版,无码影视

教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢/投訴熱線:400-618-4000

MyBatis怎樣處理一對(duì)一關(guān)聯(lián)關(guān)系?分步驟介紹

更新時(shí)間:2021年06月24日18時(shí)01分 來源:傳智教育 瀏覽次數(shù):

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

MyBatis怎樣處理一對(duì)一關(guān)聯(lián)關(guān)系

圖1 人與身份證的關(guān)聯(lián)關(guān)系

那么使用MyBatis是怎么處理圖1中的這種一對(duì)一關(guān)聯(lián)關(guān)系的呢?在<resultMap>元素中,包含了一個(gè)<association>子元素,MyBatis就是通過該元素來處理一對(duì)一關(guān)聯(lián)關(guān)系的。

在<association>元素中,通??梢耘渲靡韵聦傩裕?/p>

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

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

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

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

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

<association>元素的使用非常簡(jiǎn)單,只需要參考如下兩種示例配置即可,具體如下:

<!--方式一:嵌套查詢-->
<association property="card" column="card_id" 
javaType="com.itheima.po.IdCard"
             select="com.itheima.mapper.IdCardMapper.findCodeById" />
<!--方式二:嵌套結(jié)果-->
<association property="card" javaType="com.itheima.po.IdCard">
    <id property="id" column="card_id" />
    <result property="code" column="code" />
</association>

注意:

MyBatis在映射文件中加載關(guān)聯(lián)關(guān)系對(duì)象主要通過兩種方式:嵌套查詢和嵌套結(jié)果。嵌套查詢是指通過執(zhí)行另外一條SQL映射語(yǔ)句來返回預(yù)期的復(fù)雜類型;嵌套結(jié)果是使用嵌套結(jié)果映射來處理重復(fù)的聯(lián)合結(jié)果的子集。開發(fā)人員可以使用上述任意一種方式實(shí)現(xiàn)對(duì)關(guān)聯(lián)關(guān)系的加載。

了解了MyBatis中處理一對(duì)一關(guān)聯(lián)關(guān)系的元素和方式后,接下來就以個(gè)人和身份證之間的一對(duì)一關(guān)聯(lián)關(guān)系為例,進(jìn)行詳細(xì)講解。

查詢個(gè)人及其關(guān)聯(lián)的身份證信息是先通過查詢個(gè)人表中的主鍵來獲個(gè)人信息,然后通過表中的外鍵,來獲取證件表中的身份證號(hào)信息。其具體實(shí)現(xiàn)步驟如下:

(1)創(chuàng)建數(shù)據(jù)表。在mybatis數(shù)據(jù)庫(kù)中分別創(chuàng)建名為tb_idcard和tb_person的數(shù)據(jù)表,同時(shí)預(yù)先插入兩條數(shù)據(jù)。其執(zhí)行的SQL語(yǔ)句如下所示:

USE mybatis;
# 創(chuàng)建一個(gè)名稱為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)建一個(gè)名稱為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);

完成上述操作后,數(shù)據(jù)庫(kù)tb_idcard和tb_person表中的數(shù)據(jù)如圖2所示。

MyBatis怎樣處理一對(duì)一關(guān)聯(lián)關(guān)系

圖2 tb_idcard和tb_person表

(2)在Eclipse中創(chuàng)建一個(gè)名為chapter09的Web項(xiàng)目,然后引入相關(guān)JAR包、log4j日志文件、MybatisUtils工具類以及mybatis-config.xml核心配置文件。項(xiàng)目環(huán)境搭建完成后的文件結(jié)構(gòu),如圖3所示。

1624527322485_43.png

圖3 項(xiàng)目文件結(jié)構(gòu)

(3)在項(xiàng)目的com.itheima.po包下創(chuàng)建持久化類IdCard和Person,編輯后的代碼,如文件1和文件2所示。

文件1 IdCard.java

     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;
     /**
      * 個(gè)人持久化類
      */
     public class Person {
         private Integer id;
         private String name;
         private Integer age;
         private String sex;
         private IdCard card;  //個(gè)人關(guān)聯(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 + "]";
         }
     }

在上述兩個(gè)文件中,分別定義了各自的屬性以及對(duì)應(yīng)的getter/setter方法,同時(shí)為了方便查看輸出結(jié)果還重寫了toString()方法。

(4)在com.itheima.mapper包中,創(chuàng)建證件映射文件IdCardMapper.xml和個(gè)人映射文件PersonMapper.xml,并在兩個(gè)映射文件中編寫一對(duì)一關(guān)聯(lián)映射查詢的配置信息,如文件3和文件4所示。

文件3 IdCardMapper.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.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映射語(yǔ)句來返回預(yù)期的特殊類型 -->
         <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" />
             <!-- 一對(duì)一:association使用select屬性引入另外一條SQL語(yǔ)句 -->
             <association property="card" column="card_id" javaType="IdCard"
                 select="com.itheima.mapper.IdCardMapper.findCodeById" />
         </resultMap>
     </mapper>

在上述兩個(gè)映射文件中,使用了MyBatis中的嵌套查詢方式進(jìn)行了個(gè)人及其關(guān)聯(lián)的證件信息查詢,因?yàn)榉祷氐膫€(gè)人對(duì)象中除了基本屬性外還有一個(gè)關(guān)聯(lián)的card屬性,所以需要手動(dòng)編寫結(jié)果映射。從映射文件PersonMapper.xml中可以看出,嵌套查詢的方法是先執(zhí)行一個(gè)簡(jiǎn)單的SQL語(yǔ)句,然后在進(jìn)行結(jié)果映射時(shí),將關(guān)聯(lián)對(duì)象在<association>元素中使用select屬性執(zhí)行另一條SQL語(yǔ)句(即IdCardMapper.xml中的SQL)。

(5)在核心配置文件mybatis-config.xml中,引入Mapper映射文件并定義別名,如文件5所示。

文件5 mybatis-config.xml

     <?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ù)庫(kù)連接配置文件 -->
         <properties resource="db.properties" />
         <!--使用掃描包的形式定義別名 -->
         <typeAliases>
             <package name="com.itheima.po" />
         </typeAliases>
         <!--配置環(huán)境 ,默認(rèn)的環(huán)境id為mysql -->
         <environments default="mysql">
             <!-- 配置id為mysql的數(shù)據(jù)庫(kù)環(huán)境 -->
             <environment id="mysql">
                 <!-- 使用JDBC的事務(wù)管理 -->
                 <transactionManager type="JDBC" />
                 <!--數(shù)據(jù)庫(kù)連接池 -->
                 <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>

在上述核心配置文件中,首先引入了數(shù)據(jù)庫(kù)連接的配置文件,然后使用掃描包的形式自定義別名,接下來進(jìn)行環(huán)境的配置,最后配置了Mapper映射文件的位置信息。

(6)在com.itheima.test包中,創(chuàng)建測(cè)試類MybatisAssociatedTest,并在類中編寫測(cè)試方法findPersonByIdTest(),如文件6所示。

文件6 MybatisAssociatedTest.java

     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關(guān)聯(lián)查詢映射測(cè)試類
      */
     public class MybatisAssociatedTest {
         /**
          * 嵌套查詢
          */
         @Test
         public void findPersonByIdTest() {
             // 1、通過工具類生成SqlSession對(duì)象
             SqlSession session = MybatisUtils.getSession();
             // 2.使用MyBatis嵌套查詢的方式查詢id為1的人的信息
             Person person = session.selectOne("com.itheima.mapper." 
                                        + "PersonMapper.findPersonById", 1);
             // 3、輸出查詢結(jié)果信息
             System.out.println(person);
             // 4、關(guān)閉SqlSession
             session.close();
         }
     }

在文件6的findPersonByIdTest()方法中,首先通過MybatisUtils工具類獲取了SqlSession對(duì)象,然后通過SqlSession對(duì)象的selectOne()方法獲取了個(gè)人信息。為了查看結(jié)果,這里使用了輸出語(yǔ)句輸出查詢結(jié)果信息。最后程序執(zhí)行完畢時(shí),關(guān)閉了SqlSession。

使用JUnit4執(zhí)行findPersonByIdTest()方法后,控制臺(tái)的輸出結(jié)果如圖4所示。

MyBatis怎樣處理一對(duì)一關(guān)聯(lián)關(guān)系

圖4 運(yùn)行結(jié)果

從圖4可以看出,使用MyBatis嵌套查詢的方式查詢出了個(gè)人及其關(guān)聯(lián)的身份證信息,這就是MyBatis中的一對(duì)一關(guān)聯(lián)查詢。

雖然使用嵌套查詢的方式比較簡(jiǎn)單,但是從圖4中可以看出,MyBatis嵌套查詢的方式要執(zhí)行多條SQL語(yǔ)句,這對(duì)于大型數(shù)據(jù)集合和列表展示不是很好,因?yàn)檫@樣可能會(huì)導(dǎo)致成百上千條關(guān)聯(lián)的SQL語(yǔ)句被執(zhí)行,從而極大的消耗數(shù)據(jù)庫(kù)性能并且會(huì)降低查詢效率。這并不是開發(fā)人員所期望的。為此,我們可以使用MyBatis提供的嵌套結(jié)果方式,來進(jìn)行關(guān)聯(lián)查詢。

在PersonMapper.xml中,使用MyBatis嵌套結(jié)果的方式進(jìn)行個(gè)人及其關(guān)聯(lián)的證件信息查詢,所添加的代碼如下所示:

<!-- 嵌套結(jié)果:使用嵌套結(jié)果映射來處理重復(fù)的聯(lián)合結(jié)果的子集 -->
<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>

從上述代碼中可以看出,MyBatis嵌套結(jié)果的方式只編寫了一條復(fù)雜的多表關(guān)聯(lián)的SQL語(yǔ)句,并且在<association>元素中繼續(xù)使用相關(guān)子元素進(jìn)行數(shù)據(jù)庫(kù)表字段和實(shí)體類屬性的一一映射。

在測(cè)試類MybatisAssociatedTest中,編寫測(cè)試方法findPersonByIdTest2(),其代碼如下所示。

/**
 * 嵌套結(jié)果
 */
@Test
public void findPersonByIdTest2() {
    // 1、通過工具類生成SqlSession對(duì)象
    SqlSession session = MybatisUtils.getSession();
    // 2.使用MyBatis嵌套結(jié)果的方法查詢id為1的人的信息
    Person person = session.selectOne("com.itheima.mapper." 
                               + "PersonMapper.findPersonById2", 1);
    // 3、輸出查詢結(jié)果信息
    System.out.println(person);
    // 4、關(guān)閉SqlSession
    session.close();
}

使用JUnit4執(zhí)行findPersonByIdTest2()方法后,控制臺(tái)的輸出結(jié)果如圖5所示。

MyBatis怎樣處理一對(duì)一關(guān)聯(lián)關(guān)系

圖5 運(yùn)行結(jié)果

從圖5可以看出,使用MyBatis嵌套結(jié)果的方式只執(zhí)行了一條SQL語(yǔ)句,并且同樣查詢出了個(gè)人及其關(guān)聯(lián)的身份證的信息。

MyBatis延遲加載的配置:

在使用MyBatis嵌套查詢方式進(jìn)行MyBatis關(guān)聯(lián)查詢映射時(shí),使用MyBatis的延遲加載在一定程度上可以降低運(yùn)行消耗并提高查詢效率。MyBatis默認(rèn)沒有開啟延遲加載,需要在核心配置文件mybatis-config.xml中的<settings>元素內(nèi)進(jìn)行配置,具體配置方式如下:

<settings>
     <!-- 打開延遲加載的開關(guān) -->  
    <setting name="lazyLoadingEnabled" value="true" />  
    <!-- 將積極加載改為消息加載,即按需加載 -->  
    <setting name="aggressiveLazyLoading" value="false"/>  
</settings>

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







猜你喜歡:

Mybatis原理介紹:MyBatis如何操作數(shù)據(jù)庫(kù)?

什么是Mybatis?Mybaits有哪些優(yōu)點(diǎn)?

Mybatis執(zhí)行SQL命令是怎么實(shí)現(xiàn)的?

MyBatis中使用#和$有什么區(qū)別?

傳智教育java開發(fā)培訓(xùn)

0 分享到:
和我們?cè)诰€交談!