溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

發(fā)布時(shí)間:2021-10-19 17:32:44 來(lái)源:億速云 閱讀:93 作者:iii 欄目:編程語(yǔ)言

這篇文章主要講解了“全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式”吧!

1、Mybatis 是如何找到 SQL 語(yǔ)句的 ?

通過(guò)前面的學(xué)習(xí),我們已經(jīng)對(duì) Mybatis 的架構(gòu)設(shè)計(jì)以及核心數(shù)據(jù)層執(zhí)行流程都非常了解,其實(shí)對(duì)于我們應(yīng)用層的研發(fā)用戶來(lái)說(shuō),使用 Mybatis 框架的目的很簡(jiǎn)單,就是希望通過(guò)它來(lái)消除原有 JDBC 的冗余代碼邏輯、減輕我們開(kāi)發(fā)工作量、提升研發(fā)效率、以便于我們能夠?qū)W⒂?SQL 的編寫(xiě)。所以說(shuō)到底,是我們寫(xiě) SQL,Mybatis 幫我們執(zhí)行 SQL ,跟數(shù)據(jù)庫(kù)做交互,更簡(jiǎn)單來(lái)說(shuō),我們和 Mybatis 的配合就5步:

1、我們編寫(xiě) SQL

2、發(fā)號(hào)施令(調(diào)用API)

3、Mybatis 找 SQL

4、Mybatis 執(zhí)行 SQL

5、返回執(zhí)行結(jié)果

看吧,Mybatis 實(shí)實(shí)在在是數(shù)據(jù)庫(kù)交互的好幫手呢,乖巧又高效,我們只需編寫(xiě)好 SQL ,在程序應(yīng)用中就可以隨處發(fā)號(hào)施令(調(diào)用API),讓 Mybatis 幫我們具體執(zhí)行 SQL。但其實(shí)我們知道 Mybatis 默默做了許多事情,我們前面也都詳細(xì)剖析過(guò)的:

例如第1步編寫(xiě) SQL,其實(shí) Mybatis 就要求我們必須提前完成信息配置 Config.xml 與 映射文件 Mapper.xml (后面注解道理相同)再開(kāi)始編寫(xiě) SQL;

例如第2步發(fā)號(hào)施令,其實(shí)就是我們實(shí)際應(yīng)用當(dāng)中調(diào)用增刪改查接口( 好比sqlsession.selectList );

例如第4步執(zhí)行 SQL,其實(shí)就是會(huì)話調(diào)用執(zhí)行器,執(zhí)行器調(diào)用語(yǔ)句處理器,語(yǔ)句處理器結(jié)合參數(shù)處理器與類型處理器最終底層通過(guò) JDBC 與數(shù)據(jù)庫(kù)交互;

例如第5步返回執(zhí)行結(jié)果,是 JDBC 返回的結(jié)果集并映射封裝,最終返回預(yù)期的封裝對(duì)象。

細(xì)心的你可能會(huì)發(fā)現(xiàn),我們第3步?jīng)]說(shuō)到,那第3步是做什么的呢:Mybatis 找 SQL

到此,開(kāi)始我們本小結(jié)的研究主題:

Mybatis 是如何找到 SQL 語(yǔ)句的?

針對(duì)這個(gè)問(wèn)題,我們首先細(xì)細(xì)回想,平日里我們的 SQL 語(yǔ)句都編寫(xiě)在哪些地方呢?嗯 ~ 不出意外的話,我相信大家腦海里都會(huì)浮現(xiàn)兩個(gè)地方:一個(gè)是 XML 配置文件,另一個(gè)是 Java 注解

沒(méi)錯(cuò)!假如使用 XML 配置方式則在 UserMapper.xml 配置文件中編寫(xiě) SQL 語(yǔ)句:

<mapper namespace="com.panshenlian.dao.UserDao">

    <!-- 查詢用戶列表 -->
    <select id="findAll" resultType="com.panshenlian.pojo.User" >
        select * from User 
    </select>
    
</mapper>

使用 XML 配置方式編寫(xiě) SQL,會(huì)把 XML 中的「 命名空間標(biāo)識(shí) + 語(yǔ)句塊 ID 」作為唯一的語(yǔ)句標(biāo)識(shí),這里的唯一語(yǔ)句標(biāo)識(shí)為:

com.panshenlian.dao.UserDao.findAll

假如使用 Java 注解方式則在 UserDao 接口中編寫(xiě) SQL 語(yǔ)句:

public class UserDao {
   
    
    /** * 查詢用戶列表 * @return */
    @Select(value =" select * from User ")
    List<User> findAll();
    
}

使用 Java 注解方式編寫(xiě) SQL,會(huì)把接口中的「 接口全限定名 + 方法名 」作為唯一的語(yǔ)句標(biāo)識(shí),這里的唯一語(yǔ)句標(biāo)識(shí)也是一樣:

com.panshenlian.dao.UserDao.findAll

其實(shí),我們的 Mybatis 是支持使用 XML 配置方式和 Java 注解兩種方式來(lái)編寫(xiě) SQL 語(yǔ)句的,兩者沒(méi)有絕對(duì)的孰優(yōu)孰劣,每個(gè)項(xiàng)目團(tuán)隊(duì)都可以根據(jù)自身研發(fā)人員編碼習(xí)慣/能力、工程的耦合性要求、研發(fā)效能性價(jià)比等多方面綜合考慮之后去做選擇。畢竟無(wú)論我們使用哪種方式,目的都只是為了把實(shí)際需要執(zhí)行的 SQL 準(zhǔn)備好,供 Mybatis 跟數(shù)據(jù)庫(kù)交互時(shí)使用。

是這樣的,Mybatis 在啟動(dòng)構(gòu)建之初,會(huì)掃描我們編寫(xiě)的 SQL 文件。假如你使用 XML 配置方式編寫(xiě) SQL,那么需要在 Config.xml 核心配置文件中指定映射器文件 mapper.xml (下面代碼演示第一種);如果你使用 Java 注解方式編寫(xiě) SQL ,那么需要在 Config.xml 核心配置文件中也指定加載使用了注解的Mapper接口(下面代碼演示第二種)。

<!-- 第一種:XML配置方式:指定映射器文件 -->
<mappers>
    <mapper resource="UserMapper.xml" />
</mappers>

<!-- 第二種:Java注解方式:指定映射器接口 -->
<mappers> 
    <mapper class="com.panshenlian.dao.UserDao"/>  
</mappers>

同樣無(wú)論你使用哪一種方式告訴 Mybatis 來(lái)掃描/構(gòu)建,最終都會(huì)被統(tǒng)一加載到一個(gè) SQL 語(yǔ)句集合的大池子里面,它是一個(gè) Map 集合,以我們上面說(shuō)的 唯一語(yǔ)句標(biāo)識(shí) 作為集合的 key,以每一條 SQL 語(yǔ)句對(duì)象作為 value ,并且最終這個(gè) SQL 語(yǔ)句 Map 集合的大池子,會(huì)作為一個(gè)屬性設(shè)置在全局配置 Configuration 上面,供我們 Mybatis 在整個(gè)應(yīng)用周期里頭隨時(shí)使用。

看看,每一個(gè) SQL 語(yǔ)句都實(shí)例成一個(gè) MappedStatement 語(yǔ)句對(duì)象,并且這個(gè) SQL 語(yǔ)句 Map 集合的大池子,會(huì)作為全局配置 Configuration 的屬性 mappedStatements 。

// Mybatis 全局配置對(duì)象
public class Configuration{
   
    
    // 存儲(chǔ)SQL語(yǔ)句的集合池 
    Map<String, MappedStatement> mappedStatements 
        = new StrictMap<MappedStatement>
}

基本簡(jiǎn)單的 SQL 語(yǔ)句解析過(guò)程:

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

到這里,我相信有部分好奇的朋友還是想知道,那 Mybatis 是如何把我們編寫(xiě)的每一條 SQL 語(yǔ)句加載到語(yǔ)句集合大池子的呢?又是怎么保證每條語(yǔ)句在集合大池子中的 Key 值(唯一語(yǔ)句標(biāo)識(shí))是唯一不會(huì)重復(fù)的呢?

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

嗯,我們抱著好奇的小腦袋,對(duì)這兩個(gè)疑問(wèn)進(jìn)行探索:

1、Mybatis 是如何把我們編寫(xiě)的每一條 SQL 語(yǔ)句加載到語(yǔ)句集合大池子的呢?

首先,我們看看 Mybatis 在初始構(gòu)建會(huì)話時(shí),會(huì)通過(guò)加載核心配置文件,獲得會(huì)話工廠對(duì)象:

//加載核心配置文件
InputStream is = 
    Resources.getResourceAsStream("SqlMapConfig.xml");

// 獲得sqlSession工廠對(duì)象
SqlSessionFactory f = 
    new SqlSessionFactoryBuilder().build(is);

我們跟蹤了源代碼,發(fā)現(xiàn)會(huì)話工廠構(gòu)建器 SqlSessionFactoryBuilder 的build() 邏輯中,在實(shí)現(xiàn)會(huì)話工廠實(shí)例構(gòu)建的同時(shí),會(huì)解析配置文件并封裝成全局配置對(duì)象 Configuration 和語(yǔ)句對(duì)象集合 MappedStatement 。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

用殊途同歸,來(lái)形容 XML 配置方式和 Java 注解方式編寫(xiě) SQL 并構(gòu)建語(yǔ)句集合的過(guò)程再好不過(guò)了。

2、Mybatis 是怎么保證每條語(yǔ)句在集合大池子中的 Key 值(唯一語(yǔ)句標(biāo)識(shí))是唯一不會(huì)重復(fù)的呢??

根據(jù)第1個(gè)問(wèn)題的分析結(jié)果,我們知道 SQL 語(yǔ)句最終會(huì)被存放在語(yǔ)句集合中,那這個(gè)語(yǔ)句集合是普通 Map 嗎?顯示不是,這個(gè)集合實(shí)例其實(shí)是 Mybatis 框架在 Configuration 全局配置對(duì)象中的一個(gè)靜態(tài)的匿名內(nèi)部類 StrictMap,它繼承 HashMap ,重寫(xiě)了 put() 方法,在 put() 中實(shí)現(xiàn)對(duì) Key 值(唯一語(yǔ)句標(biāo)識(shí))的重復(fù)校驗(yàn)。

// 全局配置
public class Configuration {
   
    
    // 靜態(tài)匿名內(nèi)部類
    protected static class 
        StrictMap<V> extends HashMap<String, V> {
   
        
        // 重寫(xiě)了put方法
        @Override 
    	public V put(String key, V value) {
   
            
          // 如果出現(xiàn)重復(fù)key則拋出異常
          if (containsKey(key)) {
   
            throw 重復(fù)異常;
          } 
    	} 
    }
}

所以,無(wú)論是使用 XML 配置方式還是 Java 注解方式,都必須保證每條 SQL 語(yǔ)句有一個(gè) 唯一的語(yǔ)句標(biāo)識(shí),否則在 Mybatis 啟動(dòng)構(gòu)建階段,就會(huì)收到來(lái)自 Mybatis 的解析異常,例如我在 UserMapper.xml 中設(shè)置兩個(gè) findAll 語(yǔ)句。

<select id="findAll">
    select 1 from User
</select>

<select id="findAll">
    select * from User
</select>

不出意外,出現(xiàn) Mybatis 解析 SQL 的異常警告:

// 異常定位很準(zhǔn)確 --> 解析 mapper sql 時(shí)
### org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration.

// 哪個(gè) mapper 文件呢 --> UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'UserMapper.xml'

// 哪個(gè) id 重復(fù)了呢 --> findAll
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.panshenlian.dao.IUserDao.findAll. please check UserMapper.xml and UserMapper.xml

好,到這里我們基本清晰,SQL 怎么存,并且怎么不重復(fù)的存,而且存在哪?那剩下的就很簡(jiǎn)單,對(duì)于一個(gè) Map 集合的取值,我相信大家都知道,無(wú)非就是通過(guò) key 來(lái)取到存儲(chǔ)的 value 值。而 Mybatis 中這個(gè)語(yǔ)句集合的取值方式也是一樣通過(guò) key 值來(lái)去,這個(gè) key 呢,我們這里是每一條語(yǔ)句的 唯一語(yǔ)句標(biāo)識(shí) ,當(dāng)我們調(diào)用會(huì)話 SqlSession 的增刪改查 API 的時(shí)候,就會(huì)傳遞這個(gè)唯一語(yǔ)句標(biāo)識(shí),告訴 Mybatis :“ 幫我們把這個(gè) key 對(duì)應(yīng)的語(yǔ)句對(duì)象的 SQL 執(zhí)行一下吧 “ ,僅此而已。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

只不過(guò),這里面當(dāng)我們應(yīng)用層的用戶調(diào)用增刪改查 API 的時(shí)候,我們到底是 **如何把 Key 值告知給 Mybatis 呢?**是 直接 告訴 Mybatis 呢?還是委婉的(通過(guò)代理方式)告訴 Mybatis 。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

這個(gè)就比較有意思了,也是我們第3部分主題要講解的內(nèi)容,我們下面會(huì)細(xì)說(shuō),先看第2部分主題吧~

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

2、為什么有 Dao 層 ?

在軟件開(kāi)發(fā)中,為了方便應(yīng)用程序的研發(fā)與維護(hù),一般我們都會(huì)使用清晰合理的框架模式來(lái)規(guī)范開(kāi)發(fā)行為,提高同模塊內(nèi)聚性,減低異模塊耦合性,例如 MVC、MVP、MVVM 等,而其中 MVC(Model-View-Controller) 則是 Java 語(yǔ)言中應(yīng)用最廣泛的分層框架模式。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

對(duì)于 MVC 分層模式,其實(shí)最早的設(shè)計(jì)來(lái)源于桌面應(yīng)用程序,一般 M 代表業(yè)務(wù)模型 Model,V 代表視圖界面 view,C 代表控制器 Controller ,一般的:

View (視圖層):視圖層直接面向用戶/終端,提供給用戶/終端的指令輸入或界面操作請(qǐng)求。

Controller (控制層):控制層負(fù)責(zé)接收 “視圖層” 的指令或操作請(qǐng)求,并轉(zhuǎn)移分派至 “模型層”,接收到 “模型層” 的返回結(jié)果之后,會(huì)同步傳送回 “視圖層”,達(dá)到控制/紐帶的作用。

Model (模型層):模型層是核心的數(shù)據(jù)信息處理層,分為業(yè)務(wù)邏輯處理與數(shù)據(jù)持久化處理,模型層接收來(lái)自 “控制層” 的請(qǐng)求,并通過(guò)邏輯運(yùn)算與數(shù)據(jù)轉(zhuǎn)換,再把處理結(jié)果返回到 “控制層”。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

從程序編碼角度看,我們使用 MVC 的主要目的就是將 M 層與 V 層的實(shí)現(xiàn)代碼分離,方便代碼分層設(shè)計(jì)與維護(hù);從結(jié)果形態(tài)角度分析,其實(shí) M 層與 V 層可以理解為相同信息(或物質(zhì))的不同表現(xiàn)形態(tài),類比水與冰、或水與氣(可能不恰當(dāng),But 我確實(shí)理解為信息/物質(zhì)形態(tài)轉(zhuǎn)移),而 C 層的存在目的就是為了連接轉(zhuǎn)移 M 層與 V 層,保證 M 層與 V 層的同步/更新。

那有好奇的朋友就想知道,上面這介紹的 MVC 框架模式,跟我們 Dao 層有什么關(guān)系呢?

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

那必須有關(guān)系!

我們知道在 MVC 框架模式中,模型層 Model 是核心的數(shù)據(jù)信息處理層,包括業(yè)務(wù)邏輯處理與數(shù)據(jù)持久化處理,其中業(yè)務(wù)邏輯處理我們劃為 Service 模塊,負(fù)責(zé)具體業(yè)務(wù)需求對(duì)應(yīng)的運(yùn)算邏輯;數(shù)據(jù)持久化處理我們劃為 Dao 模塊(全稱 Data Access Object ,即數(shù)據(jù)訪問(wèn)對(duì)象),負(fù)責(zé)與數(shù)據(jù)庫(kù)交互,連接 Service 模塊與數(shù)據(jù)庫(kù)。所以只要是跟數(shù)據(jù)庫(kù)打交道,我們的 Dao 層就必不可少!

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

到這里,我相信很多朋友會(huì)聯(lián)想到,Dao 模塊是負(fù)責(zé)數(shù)據(jù)持久化處理 ,而我們的 Mybatis 不就是一個(gè)持久層框架嗎?沒(méi)錯(cuò),所以跟數(shù)據(jù)庫(kù)打交道的活,Mybatis 框架絕對(duì)是能全權(quán)負(fù)責(zé),所以當(dāng)我們的項(xiàng)目應(yīng)用集成 Mybatis 框架之后, Mybatis 的增刪改查等 API 就基本在 Dao 模塊中使用,并且接口調(diào)用與代碼實(shí)現(xiàn)也是極為簡(jiǎn)單便捷。

第3部分,我們講講本文的關(guān)鍵主題 “ Dao 層的兩種實(shí)現(xiàn)方式:傳統(tǒng)與代理 ”。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

3、Dao 層的兩種實(shí)現(xiàn)方式:傳統(tǒng)與代理

有了前面兩點(diǎn)作為基礎(chǔ),我們的第三個(gè)主題《 Dao 層的兩種實(shí)現(xiàn)方式:傳統(tǒng)與代理 》的內(nèi)容講解會(huì)讓大家很容易接受,因?yàn)槲覀冊(cè)诘谝徊糠种黝}中花大篇幅闡明 Mybatis 是如何找到 SQL 語(yǔ)句的,讓大家對(duì)于 SQL 語(yǔ)句的尋找有了全面的了解,所以我在此處先提前跟大家劇透:Dao 層的兩種實(shí)現(xiàn)方式:傳統(tǒng)與代理 ,可以粗糙的理解為他兩僅僅在SQL 語(yǔ)句的 尋找方式執(zhí)行對(duì)象 上存在區(qū)別而已。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

我們先簡(jiǎn)單看看我們一般的工程目錄結(jié)構(gòu)簡(jiǎn)例(掐頭去尾只留下基本的 MVC 目錄骨架)。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

一般 Dao 層 傳統(tǒng)上 的代碼實(shí)現(xiàn)方式:

1、編寫(xiě)UserDao接口

public interface UserDao {
    
    List<User> findAll() ; 
}

2、編寫(xiě)UserDaoImpl實(shí)現(xiàn)

public class UserDaoImpl implements UserDao {
    
    
    @Override
    public List<User> findAll() {
    
        
        //加載核心配置文件
        InputStream is = Resources.getResourceAsStream("config.xml");

        // 獲得sqlSession工廠對(duì)象
        SqlSessionFactory fy = new SqlSessionFactoryBuilder().build(is);

        //獲得sqlSession對(duì)象
        SqlSession sqlSession = fy.openSession();

        // 執(zhí)行sql語(yǔ)句
        List<User> userList = sqlSession.selectList("dao.UserDao.findAll");
        
        return userList;
       
    }
}

3、編寫(xiě) UserMapper.xml

<mapper namespace="dao.UserDao">

    <select id="findAll">
        select * from User
    </select>

</mapper>

4、Dao 層調(diào)用 (通過(guò)應(yīng)用程序的 Service 層調(diào)用或者直接使用 Junit 框架進(jìn)行測(cè)試)

// Service 服務(wù)層調(diào)用 
// 或
// Junit 測(cè)試框架測(cè)試

@Test 
public void tesDaoMethod(){
   
    UserDao userDao = new UserDaoImpl(); 
	List<User> userList = userDao.findAll();
    System.out.println(userList);
}

以上調(diào)用結(jié)果可以獲取到所有 User 記錄,這種通過(guò)在 Dao層定義接口、并創(chuàng)建 Dao 層接口實(shí)現(xiàn)類的方式,我們一般稱之為 Dao 層的傳統(tǒng)實(shí)現(xiàn)方式,此方式會(huì)構(gòu)建一個(gè)接口實(shí)現(xiàn)類去作為 Dao 層的執(zhí)行對(duì)象,并且對(duì)于 SQL 語(yǔ)句的找尋方式特別簡(jiǎn)單直接,直接指定唯一語(yǔ)句標(biāo)識(shí),Java 文件中存在硬編碼, 例如本示例中的 SQL 語(yǔ)句唯一標(biāo)識(shí)為: dao.UserDao.findAll。

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

介紹完傳統(tǒng)的開(kāi)發(fā)實(shí)現(xiàn)方式,我們說(shuō)說(shuō) Dao 層的代理開(kāi)發(fā)實(shí)現(xiàn)方式吧,首先 Dao 層的代理開(kāi)發(fā)方式有什么特別呢?

首先代理開(kāi)發(fā)實(shí)現(xiàn)方式只需我們編寫(xiě) Dao 接口而不需要編寫(xiě)實(shí)現(xiàn)類。

那么既然不用編寫(xiě)實(shí)現(xiàn)類,是不是會(huì)有一些其它方面的約束呢?

那是當(dāng)然了,這種代理開(kāi)發(fā)實(shí)現(xiàn)方式,要求我們的接口與配置文件 Mapper.xml 需要遵循一些規(guī)范:

1) Mapper.xml 文件中的 namespace 與 mapper 接口的全限定名相同
2) Mapper 接口方法名和 Mapper.xml 中定義的每個(gè) statement 的 id 相同
3) Mapper 接口方法的輸入?yún)?shù)類型和 mapper.xml 中定義的每個(gè) sql 的 parameterType 的類型相同
4) Mapper 接口方法的輸出參數(shù)類型和 mapper.xml 中定義的每個(gè) sql 的 resultType 的類型相同

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

由于代理開(kāi)發(fā)實(shí)現(xiàn)方式與 Mapper 配置緊密關(guān)聯(lián),故此我們也稱之為 Mapper 接口開(kāi)發(fā)方法,之所以不需要編寫(xiě)實(shí)現(xiàn)類的原因是其底層創(chuàng)建了 Dao 接口的動(dòng)態(tài)代理對(duì)象,代理對(duì)象本身會(huì)構(gòu)建有 Dao 接口的方法體, Dao 層 代理實(shí)現(xiàn)方式 的代碼實(shí)現(xiàn)方式:

1、編寫(xiě)UserDao接口

public interface UserDao {
    
    User findOne( int userId ) ; 
}

2、編寫(xiě) UserMapper.xml

<mapper namespace="dao.UserDao">
    <select id="findOne" parameterType="int" resultType="user">
    	select * from User where id =#{id}
    </select>
</mapper>

3、Dao 層調(diào)用 (通過(guò)應(yīng)用程序的 Service 層調(diào)用或者直接使用 Junit 框架進(jìn)行測(cè)試)

// Service 服務(wù)層調(diào)用 
// 或
// Junit 測(cè)試框架測(cè)試

@Test 
public void tesDaoMethod(){
   
    
    //加載核心配置文件
    InputStream is = Resources.getResourceAsStream("config.xml");

    // 獲得sqlSession工廠對(duì)象
    SqlSessionFactory fy = new SqlSessionFactoryBuilder().build(is);

    //獲得sqlSession對(duì)象
    SqlSession sqlSession = fy.openSession(); 

    //獲得MyBatis框架生成的 UserMapper接口的代理類
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
    
    //代理類執(zhí)行SQL
    User user = userMapper.findById(1); 
    System.out.println(user); 
    sqlSession.close(); 
}

以上調(diào)用結(jié)果可以獲取到了指定 ID 的 User 記錄,此方式通過(guò)代理執(zhí)行實(shí)際 SQL 語(yǔ)句,由于 Dao 接口與 Mapper.xml 配置已經(jīng)約定好規(guī)范,所以不需要在調(diào)用接口時(shí)指定唯一語(yǔ)句標(biāo)識(shí),Java 文件中也不會(huì)存在硬編碼問(wèn)題。

到這里,就會(huì)有部分朋友疑惑? sqlSession 會(huì)話通過(guò) getMapper 獲取接口代理類之后去調(diào)用接口方法,那到底實(shí)際執(zhí)行接口方法的時(shí)候,Mybatis 的代理在代碼邏輯上是怎么跟 mapper.xml 配置文件中的 SQL 語(yǔ)句對(duì)應(yīng)匹配起來(lái)的呢?

全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式

上圖黑色 ① ~ ⑥ ,是構(gòu)建 Dao 代理對(duì)象的實(shí)際過(guò)程,基本就是生成代理對(duì)象的過(guò)程,其中 MapperProxy 代理類本身實(shí)現(xiàn)了 InvocationHandler 接口,所以符合一個(gè)代理類的要求,MapperProxy 代理實(shí)例最終是指派 MapperMethod 對(duì)象進(jìn)行語(yǔ)句分發(fā)執(zhí)行,包含增刪改查等操作。

上圖紅色 ① ~ ③ ,是代理對(duì)象在執(zhí)行實(shí)際接口時(shí)根據(jù)接口全限定名去 SQL 語(yǔ)句集合池查找 SQL 具體語(yǔ)句的過(guò)程。

// 實(shí)際語(yǔ)句執(zhí)行方法對(duì)象
public class MapperMethod{
   
    // 根據(jù)指令類型分配執(zhí)行SQL
	public Object execute(SqlSession sqlSession, Object[] args) {
   
        switch (command.getType()) {
   
      		case INSERT: sqlSession.insert(接口語(yǔ)句ID); break;
      		case UPDATE: sqlSession.update(接口語(yǔ)句ID); break;
      		case DELETE: sqlSession.insert(接口語(yǔ)句ID); break;
      		case SELECT: sqlSession.select(接口語(yǔ)句ID); break;
        }
	}   
}

感謝各位的閱讀,以上就是“全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)全息視角看Dao層兩種實(shí)現(xiàn)方式之有哪些傳統(tǒng)方式與代理方式這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI