日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
MapperXML的解析和注冊(cè)使用

一、前言

其實(shí)很多程序員在剛開(kāi)始做編程或者新加入一家公司時(shí),都沒(méi)有多少機(jī)會(huì)可以做一個(gè)新項(xiàng)目,大部分時(shí)候都是在老項(xiàng)目上不斷的迭代更新。在這個(gè)過(guò)程你可能要學(xué)習(xí)N個(gè)前人留下的各式各樣的風(fēng)格迥異的代碼片段,在這些縱橫交錯(cuò)的流程中,找到一席之地,把自己的ifelse加進(jìn)去。

康保網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),康保網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為康保近千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的康保做網(wǎng)站的公司定做!

雖然這樣胡亂的加ifelse,剛上手就“擺爛”的心態(tài),讓人很難受。但要想在已經(jīng)被壓縮的工期下,還能交付出高質(zhì)量的代碼其實(shí)也很難完成,所以一部分研發(fā)被逼到能用就行,能跑就可以。

但說(shuō)回來(lái),其實(shí)不能逐步清理一片屎山,讓代碼在你的手上逐步清晰、整潔、干凈,很多時(shí)候也是作為碼農(nóng)自身經(jīng)驗(yàn)的不足,不懂得系統(tǒng)重構(gòu)、不了解設(shè)計(jì)原則、不熟悉業(yè)務(wù)背景、不清楚產(chǎn)品走向等等原因造成的。所以最好的辦法是提升自身的能力,每接到一次需求都有一些技術(shù)上的改變,既然它是屎山,那就當(dāng)做打怪升級(jí)了,修一點(diǎn)、改一塊、補(bǔ)一片,總會(huì)在你手上越來(lái)越易于維護(hù)和擴(kuò)展的。

二、目標(biāo)

在我們漸進(jìn)式的逐步實(shí)現(xiàn) Mybatis 框架過(guò)程中,首先我們要有一個(gè)目標(biāo)導(dǎo)向的思路,也就是說(shuō) Mybatis 的核心邏輯怎么實(shí)現(xiàn)。

其實(shí)我們可以把這樣一個(gè) ORM 框架的目標(biāo),簡(jiǎn)單的描述成是為了給一個(gè)接口提供代理類(lèi),類(lèi)中包括了對(duì) Mapper 也就是 xml 文件中的 SQL 信息(類(lèi)型、入?yún)?、出參、條件)進(jìn)行解析和處理,這個(gè)處理過(guò)程就是對(duì)數(shù)據(jù)庫(kù)的操作以及返回對(duì)應(yīng)的結(jié)果給到接口。如圖 4-1

圖 4-1 ORM 框架核心流程

那么按照 ORM 核心流程的執(zhí)行過(guò)程,我們本章節(jié)就需要在上一章節(jié)的基礎(chǔ)上,繼續(xù)擴(kuò)展對(duì) Mapper 文件的解析以及提取出對(duì)應(yīng)的 SQL 文件。并在當(dāng)前這個(gè)階段,可以滿足我們調(diào)用 DAO 接口方法的時(shí)候,可以返回 Mapper 中對(duì)應(yīng)的待執(zhí)行 SQL 語(yǔ)句。為了不至于把整個(gè)工程撐大,小傅哥會(huì)帶著大家逐步完成這些內(nèi)容,所以本章節(jié)暫時(shí)不會(huì)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作,待后續(xù)逐步實(shí)現(xiàn)

三、設(shè)計(jì)

結(jié)合上一章節(jié)我們使用了 MapperRegistry 對(duì)包路徑進(jìn)行掃描注冊(cè)映射器,并在 DefaultSqlSession 中進(jìn)行使用。那么在我們可以把這些命名空間、SQL描述、映射信息統(tǒng)一維護(hù)到每一個(gè) DAO 對(duì)應(yīng)的 Mapper XML 的文件以后,其實(shí) XML 就是我們的源頭了。通過(guò)對(duì) XML 文件的解析和處理就可以完成 Mapper 映射器的注冊(cè)和 SQL 管理。這樣也就更加我們操作和使用了。如圖 4-2

圖 4-2 XML 文件解析注冊(cè)處理

  • 首先需要定義 SqlSessionFactoryBuilder 工廠建造者模式類(lèi),通過(guò)入口 IO 的方式對(duì) XML 文件進(jìn)行解析。當(dāng)前我們主要以解析 SQL 部分為主,并注冊(cè)映射器,串聯(lián)出整個(gè)核心流程的脈絡(luò)。
  • 文件解析以后會(huì)存放到 Configuration 配置類(lèi)中,接下來(lái)你會(huì)看到這個(gè)配置類(lèi)會(huì)被串聯(lián)到整個(gè) Mybatis 流程中,所有內(nèi)容存放和讀取都離不開(kāi)這個(gè)類(lèi)。如我們?cè)?DefaultSqlSession 中獲取 Mapper 和執(zhí)行 selectOne 也同樣是需要在 Configuration 配置類(lèi)中進(jìn)行讀取操作。

四、實(shí)現(xiàn)

1. 工程結(jié)構(gòu)

mybatis-step-03
└── src
├── main
│ └── java
│ └── cn.bugstack.mybatis
│ ├── binding
│ │ ├── MapperMethod.java
│ │ ├── MapperProxy.java
│ │ ├── MapperProxyFactory.java
│ │ └── MapperRegistry.java
│ ├── builder
│ │ ├── xml
│ │ │ └── XMLConfigBuilder.java
│ │ └── BaseBuilder.java
│ ├── io
│ │ └── Resources.java
│ ├── mapping
│ │ ├── MappedStatement.java
│ │ └── SqlCommandType.java
│ └── session
│ ├── defaults
│ │ ├── DefaultSqlSession.java
│ │ └── DefaultSqlSessionFactory.java
│ ├── Configuration.java
│ ├── SqlSession.java
│ ├── SqlSessionFactory.java
│ └── SqlSessionFactoryBuilder.java
└── test
├── java
│ └── cn.bugstack.mybatis.test.dao
│ ├── dao
│ │ └── IUserDao.java
│ ├── po
│ │ └── User.java
│ └── ApiTest.java
└── resources
├── mapper
│ └──User_Mapper.xml
└── mybatis-config-datasource.xml

工程源碼:https://t.zsxq.com/bmqNFQ7

XML 解析和注冊(cè)類(lèi)實(shí)現(xiàn)關(guān)系,如圖 4-2

圖 4-2 XML 解析和注冊(cè)類(lèi)實(shí)現(xiàn)關(guān)系

  • SqlSessionFactoryBuilder 作為整個(gè) Mybatis 的入口,提供建造者工廠,包裝 XML 解析處理,并返回對(duì)應(yīng) SqlSessionFactory 處理類(lèi)。
  • 通過(guò)解析把 XML 信息注冊(cè)到 Configuration 配置類(lèi)中,再通過(guò)傳遞 Configuration 配置類(lèi)到各個(gè)邏輯處理類(lèi)里,包括 DefaultSqlSession 中,這樣就可以在獲取映射器和執(zhí)行SQL的時(shí)候,從配置類(lèi)中拿到對(duì)應(yīng)的內(nèi)容了。

2. 構(gòu)建SqlSessionFactory建造者工廠

源碼詳見(jiàn):cn.bugstack.mybatis.session.SqlSessionFactoryBuilder

public class SqlSessionFactoryBuilder {

public SqlSessionFactory build(Reader reader) {
XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder(reader);
return build(xmlConfigBuilder.parse());
}

public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}

}
  • SqlSessionFactoryBuilder 是作為整個(gè) Mybatis 的入口類(lèi),通過(guò)指定解析XML的IO,引導(dǎo)整個(gè)流程的啟動(dòng)。
  • 從這個(gè)類(lèi)開(kāi)始新增加了 XMLConfigBuilder、Configuration 兩個(gè)處理類(lèi),分別用于解析 XML 和串聯(lián)整個(gè)流程的對(duì)象保存操作。接下來(lái)我們會(huì)分別介紹這些新引入的對(duì)象。

3. XML 解析處理

源碼詳見(jiàn):cn.bugstack.mybatis.builder.xml.XMLConfigBuilder

public class XMLConfigBuilder extends BaseBuilder {

private Element root;

public XMLConfigBuilder(Reader reader) {
// 1. 調(diào)用父類(lèi)初始化Configuration
super(new Configuration());
// 2. dom4j 處理 xml
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(new InputSource(reader));
root = document.getRootElement();
} catch (DocumentException e) {
e.printStackTrace();
}
}

public Configuration parse() {
try {
// 解析映射器
mapperElement(root.element("mappers"));
} catch (Exception e) {
throw new RuntimeException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
return configuration;
}

private void mapperElement(Element mappers) throws Exception {
List mapperList = mappers.elements("mapper");
for (Element e : mapperList) {
// 解析處理,具體參照源碼

// 添加解析 SQL
configuration.addMappedStatement(mappedStatement);
}

// 注冊(cè)Mapper映射器
configuration.addMapper(Resources.classForName(namespace));
}
}

}
  • XMLConfigBuilder 核心操作在于初始化 Configuration,因?yàn)?Configuration 的使用離解析 XML 和存放是最近的操作,所以放在這里比較適合。
  • 之后就是具體的 parse() 解析操作,并把解析后的信息,通過(guò) Configuration 配置類(lèi)進(jìn)行存放,包括:添加解析 SQL、注冊(cè)Mapper映射器。
  • 解析配置整體包括:類(lèi)型別名、插件、對(duì)象工廠、對(duì)象包裝工廠、設(shè)置、環(huán)境、類(lèi)型轉(zhuǎn)換、映射器,但目前我們還不需要那么多,所以只做一些必要的 SQL 解析處理。

4. 通過(guò)配置類(lèi)包裝注冊(cè)機(jī)和SQL語(yǔ)句

**源碼詳見(jiàn)(配置項(xiàng))**:cn.bugstack.mybatis.session.Configuration

public class Configuration {

/**
* 映射注冊(cè)機(jī)
*/
protected MapperRegistry mapperRegistry = new MapperRegistry(this);

/**
* 映射的語(yǔ)句,存在Map里
*/
protected final Map mappedStatements = new HashMap<>();

public void addMapper(Class type) {
mapperRegistry.addMapper(type);
}

public void addMappedStatement(MappedStatement ms) {
mappedStatements.put(ms.getId(), ms);
}
}

在配置類(lèi)中添加映射器注冊(cè)機(jī)和映射語(yǔ)句的存放;

映射器注冊(cè)機(jī)是我們上一章節(jié)實(shí)現(xiàn)的內(nèi)容,用于注冊(cè) Mapper 映射器鎖提供的操作類(lèi)。

另外一個(gè) MappedStatement 是本章節(jié)新添加的 SQL 信息記錄對(duì)象,包括記錄:SQL類(lèi)型、SQL語(yǔ)句、入?yún)㈩?lèi)型、出參類(lèi)型等。詳細(xì)可參照源碼

5. DefaultSqlSession結(jié)合配置項(xiàng)獲取信息

源碼詳見(jiàn):cn.bugstack.mybatis.session.defaults.DefaultSqlSession

public class DefaultSqlSession implements SqlSession {

private Configuration configuration;

@Override
public T selectOne(String statement, Object parameter) {
MappedStatement mappedStatement = configuration.getMappedStatement(statement);
return (T) ("你被代理了!" + "\n方法:" + statement + "\n入?yún)ⅲ? + parameter + "\n待執(zhí)行SQL:" + mappedStatement.getSql());
}

@Override
public T getMapper(Class type) {
return configuration.getMapper(type, this);
}

}

DefaultSqlSession 相對(duì)于上一章節(jié),小傅哥這里把 MapperRegistry mapperRegistry 替換為 Configuration configuration,這樣才能傳遞更豐富的信息內(nèi)容,而不只是注冊(cè)器操作。

之后在 DefaultSqlSession#selectOne、DefaultSqlSession#getMapper 兩個(gè)方法中都使用 configuration 來(lái)獲取對(duì)應(yīng)的信息。

目前 selectOne 方法中只是把獲取的信息進(jìn)行打印,后續(xù)將引入 SQL 執(zhí)行器進(jìn)行結(jié)果查詢并返回。

五、測(cè)試

1. 事先準(zhǔn)備

提供 DAO 接口和對(duì)應(yīng)的 Mapper xml 配置

public interface IUserDao {

String queryUserInfoById(String uId);

}




2. 單元測(cè)試

@Test
public void test_SqlSessionFactory() throws IOException {
// 1. 從SqlSessionFactory中獲取SqlSession
Reader reader = Resources.getResourceAsReader("mybatis-config-datasource.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();

// 2. 獲取映射器對(duì)象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);

// 3. 測(cè)試驗(yàn)證
String res = userDao.queryUserInfoById("10001");
logger.info("測(cè)試結(jié)果:{}", res);
}
  • 目前的使用方式就和 Mybatis 非常像了,通過(guò)加載 xml 配置文件,交給 SqlSessionFactoryBuilder 進(jìn)行構(gòu)建解析,并獲取 SqlSessionFactory 工廠。這樣就可以順利的開(kāi)啟 Session 以及完成后續(xù)的操作。

測(cè)試結(jié)果

07:07:40.519 [main] INFO  cn.bugstack.mybatis.test.ApiTest - 測(cè)試結(jié)果:你被代理了!
方法:cn.bugstack.mybatis.test.dao.IUserDao.queryUserInfoById
入?yún)ⅲ篬Ljava.lang.Object;@23223dd8
待執(zhí)行SQL:
SELECT id, userId, userHead, createTime
FROM user
where id = ?


Process finished with exit code 0

從測(cè)試結(jié)果我們可以看到,目前的代理操作已經(jīng)可以把我們從 XML 中解析的 SQL 信息進(jìn)行打印了,后續(xù)我們將結(jié)合這部分的處理繼續(xù)完成數(shù)據(jù)庫(kù)的操作。

六、總結(jié)

  • 了解 ORM 處理的核心流程,知曉目前我們所處在的步驟和要完成的內(nèi)容,只有非常清楚的知道這個(gè)代理、封裝、解析和返回結(jié)果的過(guò)程才能更好的完成整個(gè)框架的實(shí)現(xiàn)。
  • SqlSessionFactoryBuilder 的引入包裝了整個(gè)執(zhí)行過(guò)程,包括:XML 文件的解析、Configuration 配置類(lèi)的處理,讓 DefaultSqlSession 可以更加靈活的拿到對(duì)應(yīng)的信息,獲取 Mapper 和 SQL 語(yǔ)句。
  • 另外從整個(gè)工程搭建的過(guò)程中,可以看到有很多工廠模式、建造者模式、代理模式的使用,也有很多設(shè)計(jì)原則的運(yùn)用,這些技巧都可以讓整個(gè)工程變得易于維護(hù)和易于迭代。這也是研發(fā)人員在學(xué)習(xí)源碼的過(guò)程中,非常值得重點(diǎn)關(guān)注的地方。

網(wǎng)頁(yè)標(biāo)題:MapperXML的解析和注冊(cè)使用
分享URL:http://www.dlmjj.cn/article/djgphoi.html