亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Mybatis-Plus的應(yīng)用場(chǎng)景描述及注入SQL原理分析

 更新時(shí)間:2021年05月26日 08:22:40   作者:vivo互聯(lián)網(wǎng)技術(shù)  
MyBatis-Plus是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生,本文重點(diǎn)給大家介紹Mybatis-Plus的應(yīng)用場(chǎng)景及注入SQL原理分析,感興趣的朋友跟隨小編一起學(xué)習(xí)吧

MyBatis-Plus(簡(jiǎn)稱(chēng) MP)是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生。

愿景是成為 MyBatis 最好的搭檔,就像 魂斗羅 中的 1P、2P,基友搭配,效率翻倍。

特性:

  • 無(wú)侵入:只做增強(qiáng)不做改變,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑
  • 損耗?。?jiǎn)?dòng)即會(huì)自動(dòng)注入基本 CURD,性能基本無(wú)損耗,直接面向?qū)ο蟛僮?/li>
  • 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service,僅僅通過(guò)少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類(lèi)使用需求
  • 支持 Lambda 形式調(diào)用:通過(guò) Lambda 表達(dá)式,方便的編寫(xiě)各類(lèi)查詢(xún)條件,無(wú)需再擔(dān)心字段寫(xiě)錯(cuò)
  • 支持主鍵自動(dòng)生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問(wèn)題
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用,實(shí)體類(lèi)只需繼承 Model 類(lèi)即可進(jìn)行強(qiáng)大的 CRUD 操作
  • 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來(lái)使用
  • 內(nèi)置分頁(yè)插件:基于 MyBatis 物理分頁(yè),開(kāi)發(fā)者無(wú)需關(guān)心具體操作,配置好插件之后,寫(xiě)分頁(yè)等同于普通 List 查詢(xún)
  • 分頁(yè)插件支持多種數(shù)據(jù)庫(kù):支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數(shù)據(jù)庫(kù)
  • 內(nèi)置性能分析插件:可輸出 Sql 語(yǔ)句以及其執(zhí)行時(shí)間,建議開(kāi)發(fā)測(cè)試時(shí)啟用該功能,能快速揪出慢查詢(xún)
  • 內(nèi)置全局?jǐn)r截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤操作

支持?jǐn)?shù)據(jù)庫(kù):

  • mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver 、 presto
  • 達(dá)夢(mèng)數(shù)據(jù)庫(kù) 、 虛谷數(shù)據(jù)庫(kù) 、 人大金倉(cāng)數(shù)據(jù)庫(kù)

一、背景

1.1 傳統(tǒng)Mybatis的弊端

1.1.1 場(chǎng)景描述

假設(shè)有兩張表:一張商品表、一張訂單表,具體表的字段如下:

現(xiàn)有如下需求:

  • 分別根據(jù)id查詢(xún)商品表和訂單表所有信息
  • 根據(jù)支付狀態(tài)和通知狀態(tài)查詢(xún)訂單表信息
  • 對(duì)訂單表增加一個(gè)訂單狀態(tài),根據(jù)訂單狀態(tài)查詢(xún)訂單信息

1.1.2 需求

需求a:根據(jù)id查詢(xún)商品表:

@Select(" SELECT p.id ,p.name ,p.picture ,p.type ,p.price, p.type, p.time
          FROM product p  where id = #{id} ")
List<Product> getProductsBYId(@Param("id") Integer id);

根據(jù)id查詢(xún)訂單表所有信息:

@Select(" SELECT o.id ,o.pay_no ,o.user_id ,o.product_id ,o.pay_price, o.num, o.pay_time, o.order_type, o.notif_type
          FROM order o  where id = #{id} ")
List<Order> getOrderBYId(@Param("id") Integer id);

需求b:根據(jù)支付狀態(tài)和通知狀態(tài)查詢(xún)訂單表信息

​@Select(" SELECT o.id ,o.pay_no ,o.user_id ,o.product_id ,o.pay_price, o.num, o.pay_time, o.order_type, o.notif_type
          FROM order o  where order_type= #{orderType} ")
List<Order> getOrderBYId(@Param("orderType") Integer orderType);
 
@Select(" SELECT o.id ,o.pay_no ,o.user_id ,o.product_id ,o.pay_price, o.num, o.pay_time, o.order_type, o.notif_type
          FROM order o  where notify_type= #{notifyType} ")
List<Order> getOrderBYId(@Param("notifyType") Integer notifyType);

需求c:對(duì)訂單表增加一個(gè)訂單狀態(tài)status,根據(jù)訂單狀態(tài)查詢(xún)訂單信息。

傳統(tǒng)mybaits需要三步:首先需要在訂單表里加個(gè)字段,然后在訂單的實(shí)體類(lèi)添加這個(gè)屬性,并且將所有dao層設(shè)計(jì)該狀態(tài)的的查詢(xún)sql都修改一遍,加上這個(gè)字段。

1.1.3 上述方式有什么問(wèn)題呢?

需求a:對(duì)于不同的實(shí)體類(lèi),即使查詢(xún)的目的一致,仍然需要重復(fù)構(gòu)造類(lèi)似的sql語(yǔ)句,僅僅是表字段和表信息不同。

需求b:對(duì)于相似的查詢(xún)條件,針對(duì)某個(gè)單一場(chǎng)景必須構(gòu)造不同的sql,造成sql語(yǔ)句的大量冗余。

需求c:將dao層所有涉及到新增字段的sql都需要修改一遍,這個(gè)過(guò)程比較繁瑣且容易出錯(cuò)。

使用mybatis-plus就可以解決上述問(wèn)題。

1.1.4 Myatis-plus的解決方案

首先讓ProductMapper和OrderMapper繼承BaseMapper類(lèi):

public interface ProductMapper extends BaseMapper<Product> {
}
 
public interface OrderMapper extends BaseMapper<Order> {
  
}

需求a:

分別根據(jù)id查詢(xún)商品表和訂單表:由于BaseMapper中提供了selectById的方法,可以直接根據(jù)具體業(yè)務(wù)場(chǎng)景,傳入指定的參數(shù)例如(id=1)即可。無(wú)需書(shū)寫(xiě)具體的sql語(yǔ)句,至于sql自動(dòng)生成的原理將在下面介紹;

productMapper.selectById(1);
orderMapper.selectById(1);

需求b:

此時(shí)利用BaseMapper.selectList(Wapper queryWrapper)方法直接構(gòu)造查詢(xún)條件,例如查詢(xún)支付狀態(tài)為2和通知狀態(tài)為1的訂單信息

orderMapper.selectList(new QueryWrapper<Order>().eq("orderType",2));
orderMapper.selectList(new QueryWrapper<Order>().eq("notifyType",1));
orderMapper.selectList(new QueryWrapper<Order>().eq("orderType",2));orderMapper.selectList(new QueryWrapper<Order>().eq("notifyType",1));

此時(shí)我們可以發(fā)現(xiàn):使用了Mybatis-plus以后,我們更加聚焦于業(yè)務(wù)本身,對(duì)于上述相似的應(yīng)用場(chǎng)景,無(wú)需構(gòu)造雷同的SQL,利用包裝器直接傳入查詢(xún)條件。

需求c:

前兩步與傳統(tǒng)mybatis一致,由于MyBatis-plus無(wú)需手動(dòng)創(chuàng)建SQL,因此減少了大量的重復(fù)勞動(dòng)。

1.2 MyBatis-Plus的定位

MyBatis-Plus (opens new window)(簡(jiǎn)稱(chēng) MP)是一個(gè) MyBatis (opens new window)的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生。

1.3 特性

  • 無(wú)侵入:只做增強(qiáng)不做改變,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑;
  • 損耗?。?jiǎn)?dòng)即會(huì)自動(dòng)注入基本 CURD,性能基本無(wú)損耗,直接面向?qū)ο蟛僮鳎?/li>
  • 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service,僅僅通過(guò)少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類(lèi)使用需求;
  • 支持 Lambda 形式調(diào)用:通過(guò) Lambda 表達(dá)式,方便的編寫(xiě)各類(lèi)查詢(xún)條件,無(wú)需再擔(dān)心字段寫(xiě)錯(cuò);
  • 支持主鍵自動(dòng)生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問(wèn)題;
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用,實(shí)體類(lèi)只需繼承 Model 類(lèi)即可進(jìn)行強(qiáng)大的 CRUD 操作;
  • 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere );
  • 內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來(lái)使用;
  • 內(nèi)置分頁(yè)插件:基于 MyBatis 物理分頁(yè),開(kāi)發(fā)者無(wú)需關(guān)心具體操作,配置好插件之后,寫(xiě)分頁(yè)等同于普通 List 查詢(xún);
  • 分頁(yè)插件支持多種數(shù)據(jù)庫(kù):支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數(shù)據(jù)庫(kù);
  • 內(nèi)置性能分析插件:可輸出 Sql 語(yǔ)句以及其執(zhí)行時(shí)間,建議開(kāi)發(fā)測(cè)試時(shí)啟用該功能,能快速揪出慢查詢(xún);
  • 內(nèi)置全局?jǐn)r截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤操作。

1.4 原理解析

本文針對(duì)MyBatis-plus中的核心功能:SQL自動(dòng)注入功能,進(jìn)行流程分析及原理探究。

二、準(zhǔn)備工作

先從一個(gè)簡(jiǎn)單的demo入手,感受一下MyBatis-plus的便捷性。

2.1 基礎(chǔ)接口BaseMapper

源碼中提供了一個(gè)基礎(chǔ)接口,里面包含了基本的增刪改查方法。

2.2 創(chuàng)建實(shí)體類(lèi)對(duì)象

2.3 業(yè)務(wù)接口UserMapper

業(yè)務(wù)中根據(jù)具體實(shí)體對(duì)象,繼承該抽象接口。

2.4 測(cè)試用例

控制臺(tái)顯示:MyBatis-plus最終為我們自動(dòng)生成了SQL語(yǔ)句。根據(jù)上述操作分析:UserMapper繼承了BaseMapper,擁有了deleteById的方法,但是MyBatis-plus是基于mybatis的增強(qiáng)版,關(guān)鍵在于最終仍然需要提供具體的SQL語(yǔ)句,來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作。

下面就通過(guò)debug由上而下分析mybatis-plus是如何生成業(yè)務(wù)sql以及自動(dòng)注入的。

三、SQL語(yǔ)句存儲(chǔ)在哪里?

mappedStatements:描述sql信息

如下圖所示:mybatis為我們生成了一個(gè)代理對(duì)象,里面包含了一些重要的屬性。

具體如下:

userMapper——>mybatisMapperProxy——>sqlSession——>sqlSessionFactory——>configuration——>mappedStatements——>mappedStatement——>sql語(yǔ)句

至此我們可以發(fā)現(xiàn)每一個(gè)SQL語(yǔ)句對(duì)應(yīng)一個(gè)mappedStatement,mappedstatements存儲(chǔ)在configuration文件(configuration是mybatis的全局配置文件,包含數(shù)據(jù)源、mapper、其他配置信息)中。

四、SQL語(yǔ)句是什么時(shí)候注入的?

4.1 AbstractMethod.addMappedStatement

基于上面的分析,想要知道SQL語(yǔ)句什么時(shí)候拿到的,就是要找到mappedStatement被添加的位置。追蹤到AbstractMethod的抽象方法中。

找到了addMappedStatement()方法

而B(niǎo)aseMapper的所有方法(deleteById、delete、insert、select、update等)都繼承了該抽象方法。

根據(jù)mapper方法(deleteById)顯然是調(diào)用addDeleteMappedStatement方法。

這里我們可以發(fā)現(xiàn),源碼中根據(jù)不同的方法繼承AbstractMethod實(shí)現(xiàn)了不同的實(shí)現(xiàn)類(lèi),并且實(shí)現(xiàn)了injectMappedStatement方法,sqlSource也是在這個(gè)地方被添加進(jìn)配置文件。

4.2 AbstractMethod.inject

繼續(xù)研究AbstractMethod抽象類(lèi),inject方法實(shí)現(xiàn)了自動(dòng)注入sql的動(dòng)作。

有上述源碼可知,項(xiàng)目啟動(dòng)時(shí),首先由默認(rèn)注入器生成基礎(chǔ)CRUD實(shí)現(xiàn)類(lèi)對(duì)象,其次遍歷實(shí)現(xiàn)類(lèi)列表,依次注入各自的模板SQL,最后將其添加至mappedstatement。

五、SQL語(yǔ)句是怎么生成的?

5.1 SQL模板

上述方法中有兩個(gè)關(guān)鍵的參數(shù):SqlMethod、SqlSource;

繼續(xù)研究源碼發(fā)現(xiàn):sqlMethod本質(zhì)上是一個(gè)枚舉類(lèi),存儲(chǔ)了兩個(gè)關(guān)鍵的元素:

BaseMapper中的方法名;

方法名對(duì)應(yīng)的sql語(yǔ)句模板(即被標(biāo)簽包裹的字符串)。

到這里我們基本了解了mybaits-plus實(shí)現(xiàn)sql自動(dòng)生成的本質(zhì):根據(jù)不同的方法來(lái)提供一些通用的模板,項(xiàng)目啟動(dòng)后再加載進(jìn)mappedStatement。

5.2 SqlSource

此時(shí)SqlSource通過(guò)解析SQL模板、以及傳入的表信息和主鍵信息構(gòu)建出了SQL語(yǔ)句。

5.3 數(shù)據(jù)庫(kù)表信息是如何獲取的?

分析initTableName()方法:獲取表名信息源碼中傳入了實(shí)體類(lèi)信息clazz,其實(shí)就是通過(guò)實(shí)體上的@TableName注解拿到了表名;

我們?cè)诙x實(shí)體類(lèi)的同時(shí),指定了該實(shí)體類(lèi)對(duì)應(yīng)的表名。

分析initTableFields()方法:

獲取主鍵及其他字段信息

至此tableInfo的信息已經(jīng)注入完成了。

在研究完解析mapper的核心過(guò)程之后,我們?cè)俸?jiǎn)單看下mapper文件被添加到configuration(mybatis核心配置文件)的過(guò)程。

六、mapper文件被添加的過(guò)程

ISqlInjector:Sql注入器

MybatisMapperAnnotationBuilder:mapper解析器

MybatisMapperAnnotationBuilder中的parse方法獲取了sqlInjector(Sql注入器)來(lái)進(jìn)行SQL注入。

Mybatis添加mapper的固有流程:MybatisMapperRegistry

調(diào)用MapperAnnotionBuilder解析器進(jìn)行解析

MybatisConfiguration.addMapper

MybatisXMLConfigBuilder.mapperElemnt

MybayisXMLConfigBuilder.parseConfiguration

添加mapper文件的過(guò)程分析到這里就完成了。

七、總結(jié)

7.1 流程梳理

下面總結(jié)梳理了一下mybatis-plus解析mapper文件自動(dòng)注入sql的主要流程。

7.2 Mybatis-plus的ORM的核心思想

1)實(shí)體類(lèi)和數(shù)據(jù)庫(kù)表通過(guò)自定義注解來(lái)完成一一映射。

2)對(duì)象屬性和字段同樣使用注解來(lái)一一對(duì)應(yīng)(命名注意要相同)。

3)為了提高復(fù)用性使得具體的mapper繼承通用的增刪改查接口。

4)利用模板方法和對(duì)象屬性值動(dòng)態(tài)拼接SQL。

八、參考文檔

MyBatis-plus官方文檔:https://mp.baomidou.com/

作者:vivo互聯(lián)網(wǎng)服務(wù)器團(tuán)隊(duì)-Li Lei

到此這篇關(guān)于Mybatis-Plus的應(yīng)用場(chǎng)景及注入SQL原理分析的文章就介紹到這了,更多相關(guān)Mybatis-Plus sql注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

最新評(píng)論