最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于MyBatis中映射對(duì)象關(guān)系的舉例

 更新時(shí)間:2022年06月22日 10:25:01   作者:lanyotechcs  
這篇文章主要介紹了關(guān)于MyBatis中映射對(duì)象關(guān)系的舉例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

MyBatis映射對(duì)象關(guān)系

雙向many2one/one2many關(guān)系中的組合關(guān)系(級(jí)聯(lián))

上面已經(jīng)看到了雙向many2one/one2many關(guān)系的映射。

但是我們說,在關(guān)聯(lián)關(guān)系中,還存在組合/聚合關(guān)系。

所謂聚合就是one方和many方可以獨(dú)立存在;組合關(guān)系是強(qiáng)聚合關(guān)系,one方和many方解除關(guān)系后,就沒有實(shí)際意義了。

在組合關(guān)系中,必須要處理的一個(gè)問題就是級(jí)聯(lián)關(guān)系。

下面使用SaleBill和SaleBillItem對(duì)象來完成雙向的many2one/one2many的組合關(guān)系。

對(duì)象設(shè)計(jì)如下:

//銷售單對(duì)象
public class SaleBill {
    private Long id;
    private String sn;
    private Set<</span>SaleBillItem> items = new HashSet<</span>SaleBillItem>();
    //getter & setter
}  
        
//銷售單明細(xì)對(duì)象
public class SaleBillItem {
    private Long id;
    private Double price;
    private SaleBill bill;
    //getter & setter
}
  • 對(duì)于組合關(guān)系,數(shù)據(jù)表的結(jié)構(gòu)設(shè)計(jì)和many2one一樣,都是many方一個(gè)外鍵引用one方的主鍵。
  • 在組合關(guān)系中,一般來說,明細(xì)項(xiàng)是不需要額外有一個(gè)Mapper文件的,所有的映射都應(yīng)該放在One方的映射文件中。

下面來看看映射文件:    

<mapper namespace="cd.itcast.mybatis.salebill.SaleBillMapper">
<!-- 保存SaleBill對(duì)象,該調(diào)用必須放在SaleBillItem對(duì)象保存之前 -->
    <insert id="saveSaleBill" keyProperty="id" parameterType="SaleBill"
                useGeneratedKeys="true">
                INSERT INTO salebill(sn) values (#{sn})
    </insert>
<!-- 保存SaleBillItem對(duì)象 -->
    <insert id="saveSaleBillItem" keyProperty="id" parameterType="SaleBillItem" useGeneratedKeys="true">
            INSERT INTO salebillitem(price,bill_id) values (#{price},#{bill.id})
</insert>
<!-- 內(nèi)嵌映射SaleBill對(duì)象,注意,因?yàn)槭墙M合關(guān)系,所以不會(huì)出現(xiàn)單獨(dú)去拿SaleBillItem對(duì)象的情況,所以只需要映射SaleBill主對(duì)象即可 -->
<resultMap type="SaleBill" id="salebillmap">
            <id property="id" column="id"/>
            <result column="sn" property="sn"/>
            <collection property="items" column="id" ofType="SaleBillItem" >
            <id column="item_id" property="id"/>
            <result column="item_price" property="price"/>
            <association property="bill" column="bill_id" resultMap="salebillmap" />
           </collection>
</resultMap>
 
<!-- 因?yàn)榱斜砗蛦为?dú)的get方法都是采用內(nèi)聯(lián)的查詢,所以把公用的SQL提取出來 -->
    <sql id="select">
            SELECT b.*,item.id as item_id,item.price as item_price FROM salebill b LEFT JOIN salebillitem item ON b.id = item.bill_id
     </sql>
 
<!-- get -->
    <select id="get" parameterType="long" resultMap="salebillmap">
            <include refid="select"/> WHERE b.id = #{id}
     </select>
 
<!-- 列表查詢 -->
    <select id="list" resultMap="salebillmap">
            <include refid="select"/>
     </select>
 
<!-- 刪除SaleBill對(duì)象 -->
    <delete id="delete" parameterType="long">
            DELETE FROM salebill WHERE id = #{id}      
    </delete>
 
<!-- 刪除SaleBill對(duì)象對(duì)應(yīng)的Item對(duì)象,注意,因?yàn)橛型怄I的約束,這條刪除語句應(yīng)該放在delete SaleBill之前執(zhí)行。注意,傳入的這個(gè)id應(yīng)該是SaleBill的id -->
    <delete id="deleteItems" parameterType="long">
     DELETE FROM salebillitem WHERE bill_id = #{id}
    </delete>
</mapper>

映射文件的內(nèi)容都已經(jīng)注釋詳細(xì)。

主要注意一點(diǎn)的就是在設(shè)計(jì)映射文件的時(shí)候需要考慮組合關(guān)系的一般設(shè)計(jì)方式,所以在上面的配置文件中只做了SaleBill對(duì)象的映射。

這個(gè)配置文件還是很好理解的,其中所有的配置點(diǎn)在前面都已經(jīng)介紹過。

在組合關(guān)系中,主要的問題就是一個(gè)級(jí)聯(lián)保存,但是注意,在mybatis中設(shè)計(jì)組合的級(jí)聯(lián)保存,刪除,這個(gè)過程應(yīng)該是我們自己來控制的。  

下面來看看怎么測試組合關(guān)系:

//先創(chuàng)建一個(gè)Mapper接口,使用接口來完成映射
public interface SaleBillMapper {
? ? void saveSaleBill(SaleBill sb);
? ? void saveSaleBillItem(SaleBillItem sbi);
? ? SaleBill get(Long id);
? ? //在接口中可以直接映射分頁對(duì)象
? ? List<</span>SaleBill> list(RowBounds rb);
? ? void delete(Long id);
? ? void deleteItems(Long billId);
}

具體測試代碼:

@Test
public void testSave() {
? ? //創(chuàng)建SaleBill對(duì)象
? ? SaleBill sb = new SaleBill();
? ? sb.setSn("001");
? ? //創(chuàng)建一個(gè)明細(xì)對(duì)象
? ? SaleBillItem sbi = new SaleBillItem();
? ? sbi.setPrice(100d);
? ? sbi.setBill(sb);
? ? //創(chuàng)建一個(gè)明細(xì)對(duì)象
? ? SaleBillItem sbi2 = new SaleBillItem();
? ? sbi2.setPrice(300d);
? ? sbi2.setBill(sb);
? ? //處理關(guān)系
? ? sb.getItems().add(sbi);
? ? sb.getItems().add(sbi2);
? ? //保存
? ? SqlSession session = MyBatisUtil.openSession();
? ? SaleBillMapper mapper = session.getMapper(SaleBillMapper.class);
? ? //注意,先保存SaleBill對(duì)象
? ? mapper.saveSaleBill(sb);
? ? //保存明細(xì)對(duì)象
? ? mapper.saveSaleBillItem(sbi);
? ? mapper.saveSaleBillItem(sbi2);
? ? session.commit();
? ? session.close();
}
?
@Test
public void testGet() {
? ? SqlSession session = MyBatisUtil.openSession();
? ? //得到SaleBill對(duì)象
? ? SaleBillMapper mapper = session.getMapper(SaleBillMapper.class);
? ? SaleBill sb = mapper.get(5l);
? ? Set<</span>SaleBillItem> items = sb.getItems();
? ? for (SaleBillItem item : items) {
? ? ? ? ? ? System.out.println(item.getPrice());
? ? }
? ? session.close();
}
?
@Test
public void testDelete() {
? ? SqlSession session = MyBatisUtil.openSession();
? ? SaleBillMapper mapper = session.getMapper(SaleBillMapper.class);
? ? mapper.deleteItems(1l);
? ? mapper.delete(1l);
? ? session.commit();
? ? session.close();
} ? ?

Mybatis映射原理

MyBatis的真正強(qiáng)大之處在于它的映射語句,這也是它的魔力所在。由于它的映射語句異常強(qiáng)大,映射器的 XML 文件就顯得相對(duì)簡單。

MyBatis3.0相比2.0版本的一個(gè)最大變化,就是支持使用接口來調(diào)用方法。

  • 以前使用 SqlSession 通過命名空間調(diào)用 MyBatis 方法時(shí),首先需要用到命名空間和方法id 組成的字符串來調(diào)用相應(yīng)的方法 。
  • 當(dāng)參數(shù)多于 1 個(gè)的時(shí)候,需要將所有參數(shù)放到一個(gè) Map對(duì)象中 。 通過 Map 傳遞多個(gè)參數(shù),使用起來很不方便,而且還無法避免很多重復(fù)的代碼。
  • 使用接口調(diào)用方式就會(huì)方便很多, MyBatis 使用 Java 的動(dòng)態(tài)代理可以直接通過接口來調(diào)用 相應(yīng) 的方法,不需要提供接口的實(shí)現(xiàn)類,更不需要在實(shí)現(xiàn)類中使用 SqlSess 工∞以通過命名空 間間接調(diào)用 。
  • 另外,當(dāng)有多個(gè)參數(shù)的時(shí)候,通過參數(shù)注解@ Par am 設(shè)置參數(shù)的名字省去了 手動(dòng)構(gòu)造 Map 參數(shù)的過程,尤其在 Spring 中使用的時(shí)候,可以配置為自動(dòng)掃描所有的接口類 ,直接將接口注入需要用到的地方。

mapper文件示例:

<?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.cnpiec.ireader.dao.GetBookDataDao">
? ? <insert id="batchInsertBook" parameterType="Book">
? ? ? ? INSERT INTO BOOK (BOOKID,NAME,PARTNERNAME) VALUES
? ? ? ? <foreach collection="list" item="book" separator=",">
? ? ? ? ? ? (#{book.bookId}, #{book.name}, #{book.partnerName})
? ? ? ? </foreach>
? ? </insert>
</mapper>

需要注意的是<mapper>根標(biāo)簽的 name space 屬性。當(dāng) Mapper 接口和 XML 文件關(guān)聯(lián)的時(shí)候,命名空間口amespace 的值就需要配置成接口的全限定名稱,例如 UserMapper 接口對(duì)應(yīng)的 tk. mybatis . simple .mapper . UserMapper, MyBatis 內(nèi)部就是通過這個(gè)值將接口和XML 關(guān)聯(lián)起來的。

mybati s-config.xml 配置文件中的 mappers 元素中配置所有的 mapper ,部分配置代碼如下 。

<mappers>
? ? <mapper resource=” tk/mybatis/simple/mapper/CountryMapper.xml ” / >
? ? <mapper resource=” tk/mybatis/simple/mapper/UserMapper . xml ” / >
? ? <mapper resource=” tk/mybatis/simple/mapper/RoleMapper.xml ” />
? ? <mapper resource=” tk/mybatis/simple/mapper/PrivilegeMapper . xml ” />
? ? <mapper resource=” tk/mybatis/simple/mapper/UserRoleMapper . xml ” />
? ? <mapper resource=” tk/mybatis/simple/mapper / RolePrivilegeMapper.xml ” />
</mappers>

更簡單的配置方式,代碼如下

<mappers>
? ? <package name= ” tk.mybatis . simple . mapper ” />
</mappers>

這種配置方式會(huì)先查找 tk.mybatis.simple . mapper 包下所有的接口,循環(huán)對(duì)接口進(jìn)行如下操作。這種配置方式會(huì)先查找 tk.mybatis.simple . mapper 包下所有的接口,循環(huán)對(duì)接口進(jìn)行判斷接口對(duì)應(yīng)的命名 空 間是否己經(jīng)存在,如果不存在就拋出異常,存在就繼續(xù)進(jìn)行接下來的操作。加載接口對(duì)應(yīng)的卻也映射文件 , 將接口全限定名轉(zhuǎn)換為路徑.

為什么 Mapper 接口沒有實(shí)現(xiàn)類卻能被正常調(diào)用呢?

這是因?yàn)镸yBaits 在 Mapper 接口上使用了動(dòng)態(tài)代理的一種非常規(guī)的用法,熟悉這動(dòng)態(tài)代理的用法不僅有利于理解 MyBatis 接口和 XML 的關(guān)系,還能開闊思路 。

從代理類中可以看到,當(dāng)調(diào)用 一個(gè)接口的方法時(shí),會(huì)先通過接口的全限定名稱和當(dāng)前調(diào)用的方法名的組合得到一個(gè)方法 id,這個(gè) id 的值就是映射 XML 中口arnespa ce 和具體方法 id的組合。所以可以在代理方法中使用 sqlSession 以命名空間的方式調(diào)用方法。通過這種方式可以將接口和 XML 文件中的方法關(guān)聯(lián)起來。這種代理方式和常規(guī)代理的不同之處在于,這里沒有對(duì)某個(gè)具體類進(jìn)行代理,而是通過代理轉(zhuǎn)化成了對(duì)其他代碼的調(diào)用。

由于方法參數(shù)和返回值存在很多種情況,因此 MyBatis 的內(nèi)部實(shí)現(xiàn)會(huì)比上面的邏輯復(fù)雜得多,正是因?yàn)?MyBatis 對(duì)接口動(dòng)態(tài)代理的實(shí)現(xiàn),我們在使用接口方式的時(shí)候才會(huì)如此容易。 

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis plus or and 的合并寫法實(shí)例

    mybatis plus or and 的合并寫法實(shí)例

    這篇文章主要介紹了mybatis plus or and 的合并寫法實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • SpringBoot淺析緩存機(jī)制之Redis單機(jī)緩存應(yīng)用

    SpringBoot淺析緩存機(jī)制之Redis單機(jī)緩存應(yīng)用

    在上文中我介紹了Spring Boot使用EhCache 2.x來作為緩存的實(shí)現(xiàn),本文接著介紹使用單機(jī)版的Redis作為緩存的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Maven Spring jar包啟動(dòng)報(bào)錯(cuò)問題解決方案

    Maven Spring jar包啟動(dòng)報(bào)錯(cuò)問題解決方案

    maven 編譯jar包,放在linux服務(wù)器啟動(dòng)不起來,提示:xxxx-0.0.1-SNAPSHOT.jar中沒有主清單屬性,接下來通過本文給大家分享問題原因及解決方案,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • JDK14之jpackage打包命令的使用

    JDK14之jpackage打包命令的使用

    這篇文章主要介紹了JDK14之jpackage打包命令的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java棧的運(yùn)用之中綴表達(dá)式求值詳解

    Java棧的運(yùn)用之中綴表達(dá)式求值詳解

    本文來介紹一題中綴表達(dá)式求值的問題,就是給定一個(gè)中綴計(jì)算式,編寫程序?qū)⑦@個(gè)式子運(yùn)算結(jié)果給計(jì)算出來,其實(shí)和后綴表達(dá)式的思路差不多,都是棧的運(yùn)用問題,感興趣的可以了解一下
    2022-11-11
  • 使用Spring自定義實(shí)現(xiàn)IOC和依賴注入(注解方式)

    使用Spring自定義實(shí)現(xiàn)IOC和依賴注入(注解方式)

    這篇文章主要介紹了使用Spring自定義實(shí)現(xiàn)IOC和依賴注入(注解方式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot中到底該如何解決跨域問題

    SpringBoot中到底該如何解決跨域問題

    跨域問題更是老生常談,隨便用標(biāo)題去google或百度一下,能搜出一大片解決方案,這篇文章主要給大家介紹了關(guān)于SpringBoot中到底該如何解決跨域問題的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Spring?Boot?底層原理基礎(chǔ)深度解析

    Spring?Boot?底層原理基礎(chǔ)深度解析

    這篇文章主要介紹了Spring?Boot?底層原理基礎(chǔ),包括底層注解@Configuration,底層注解@Import及底層注解@Conditional的相關(guān)知識(shí),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • JAVA Vector源碼解析和示例代碼

    JAVA Vector源碼解析和示例代碼

    本文的學(xué)習(xí)方式是先對(duì)JAVA Vector有個(gè)整體認(rèn)識(shí),然后再學(xué)習(xí)它的源碼,最后再通過實(shí)例來學(xué)會(huì)使用。
    2013-11-11
  • net.sf.json.JSONObject 為null 的判斷方法

    net.sf.json.JSONObject 為null 的判斷方法

    下面小編就為大家?guī)硪黄猲et.sf.json.JSONObject 為null 的判斷方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02

最新評(píng)論

蚌埠市| 镇安县| 仁化县| 黑水县| 柳林县| 河东区| 仪征市| 犍为县| 金平| 威远县| 景谷| 天镇县| 巴塘县| 扶余县| 井研县| 理塘县| 隆昌县| 海南省| 昌都县| 靖州| 元朗区| 招远市| 体育| 新和县| 乌拉特中旗| 峨边| 吉木乃县| 瑞安市| 鹿邑县| 德阳市| 福泉市| 广饶县| 钟祥市| 安平县| 兰西县| 威远县| 濮阳市| 仁怀市| 永城市| 澄迈县| 宜都市|