日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

java执行sql文件_面试官:MyBatis SQL是如何执行的?把这篇文章甩给他

發(fā)布時間:2025/3/19 数据库 320 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java执行sql文件_面试官:MyBatis SQL是如何执行的?把这篇文章甩给他 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

初識 MyBatis

MyBatis 是第一個支持自定義 SQL、存儲過程和高級映射的類持久框架。MyBatis 消除了大部分 JDBC 的樣板代碼、手動設置參數(shù)以及檢索結果。MyBatis 能夠支持簡單的 XML 和注解配置規(guī)則。使 Map 接口和 POJO 類映射到數(shù)據(jù)庫字段和記錄。

MyBatis 的特點

那么 MyBatis 具有什么特點呢?或許我們可以從如下幾個方面來描述

  • MyBatis 中的 SQL 語句和主要業(yè)務代碼分離,我們一般會把 MyBatis 中的 SQL 語句統(tǒng)一放在 XML 配置文件中,便于統(tǒng)一維護。
  • 解除 SQL 與程序代碼的耦合,通過提供 DAO 層,將業(yè)務邏輯和數(shù)據(jù)訪問邏輯分離,使系統(tǒng)的設計更清晰,更易維護,更易單元測試。SQL 和代碼的分離,提高了可維護性。
  • MyBatis 比較簡單和輕量

本身就很小且簡單。沒有任何第三方依賴,只要通過配置 jar 包,或者如果你使用 Maven 項目的話只需要配置 Maven 以來就可以。易于使用,通過文檔和源代碼,可以比較完全的掌握它的設計思路和實現(xiàn)。

  • 屏蔽樣板代碼

MyBatis 回屏蔽原始的 JDBC 樣板代碼,讓你把更多的精力專注于 SQL 的書寫和屬性-字段映射上。

  • 編寫原生 SQL,支持多表關聯(lián)

MyBatis 最主要的特點就是你可以手動編寫 SQL 語句,能夠支持多表關聯(lián)查詢。

  • 提供映射標簽,支持對象與數(shù)據(jù)庫的 ORM 字段關系映射

ORM 是什么?對象關系映射(Object Relational Mapping,簡稱ORM) ,是通過使用描述對象和數(shù)據(jù)庫之間映射的元數(shù)據(jù),將面向對象語言程序中的對象自動持久化到關系數(shù)據(jù)庫中。本質上就是將數(shù)據(jù)從一種形式轉換到另外一種形式。

  • 提供 XML 標簽,支持編寫動態(tài) SQL。

你可以使用 MyBatis XML 標簽,起到 SQL 模版的效果,減少繁雜的 SQL 語句,便于維護。

MyBatis 整體架構

MyBatis 最上面是接口層,接口層就是開發(fā)人員在 Mapper 或者是 Dao 接口中的接口定義,是查詢、新增、更新還是刪除操作;中間層是數(shù)據(jù)處理層,主要是配置 Mapper -> XML 層級之間的參數(shù)映射,SQL 解析,SQL 執(zhí)行,結果映射的過程。上述兩種流程都由基礎支持層來提供功能支撐,基礎支持層包括連接管理,事務管理,配置加載,緩存處理等。

接口層

在不與Spring 集成的情況下,使用 MyBatis 執(zhí)行數(shù)據(jù)庫的操作主要如下:

InputStream is = Resources.getResourceAsStream("myBatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);sqlSession = factory.openSession();

其中的SqlSessionFactory,SqlSession是 MyBatis 接口的核心類,尤其是 SqlSession,這個接口是MyBatis 中最重要的接口,這個接口能夠讓你執(zhí)行命令,獲取映射,管理事務。

數(shù)據(jù)處理層

  • 配置解析

在 Mybatis 初始化過程中,會加載 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息會形成相應的對象并保存到Configration 對象中。之后,根據(jù)該對象創(chuàng)建SqlSessionFactory 對象。待 Mybatis 初始化完成后,可以通過 SqlSessionFactory 創(chuàng)建 SqlSession 對象并開始數(shù)據(jù)庫操作。

  • SQL 解析與 scripting 模塊

Mybatis 實現(xiàn)的動態(tài) SQL 語句,幾乎可以編寫出所有滿足需要的 SQL。

Mybatis 中 scripting 模塊會根據(jù)用戶傳入的參數(shù),解析映射文件中定義的動態(tài) SQL 節(jié)點,形成數(shù)據(jù)庫能執(zhí)行的SQL 語句。

  • SQL 執(zhí)行

SQL 語句的執(zhí)行涉及多個組件,包括 MyBatis 的四大核心,它們是: Executor、StatementHandler、ParameterHandler、ResultSetHandler。SQL 的執(zhí)行過程可以用下面這幅圖來表示

MyBatis 層級結構各個組件的介紹(這里只是簡單介紹,具體介紹在后面):

  • SqlSession:,它是 MyBatis 核心 API,主要用來執(zhí)行命令,獲取映射,管理事務。接收開發(fā)人員提供 Statement Id 和參數(shù)。并返回操作結果。
  • Executor :執(zhí)行器,是 MyBatis 調度的核心,負責 SQL 語句的生成以及查詢緩存的維護。
  • StatementHandler : 封裝了JDBC Statement 操作,負責對 JDBC Statement 的操作,如設置參數(shù)、將Statement 結果集轉換成 List 集合。
  • ParameterHandler : 負責對用戶傳遞的參數(shù)轉換成 JDBC Statement 所需要的參數(shù)。
  • ResultSetHandler : 負責將 JDBC 返回的 ResultSet 結果集對象轉換成 List 類型的集合。
  • TypeHandler : 用于 Java 類型和 JDBC 類型之間的轉換。
  • MappedStatement : 動態(tài) SQL 的封裝
  • SqlSource : 表示從 XML 文件或注釋讀取的映射語句的內容,它創(chuàng)建將從用戶接收的輸入?yún)?shù)傳遞給數(shù)據(jù)庫的 SQL。
  • Configuration: MyBatis 所有的配置信息都維持在 Configuration 對象之中。

基礎支持層

  • 反射模塊

Mybatis 中的反射模塊,對 Java 反射進行了很好的封裝,提供了簡易的 API,方便上層調用,并且對反射操作進行了一系列的優(yōu)化,比如,緩存了類的 元數(shù)據(jù)(MetaClass)和對象的元數(shù)據(jù)(MetaObject),提高了反射操作的性能。

  • 類型轉換模塊

Mybatis 的別名機制,能夠簡化配置文件,該機制是類型轉換模塊的主要功能之一。類型轉換模塊的另一個功能是實現(xiàn) JDBC 類型與 Java 類型的轉換。在 SQL 語句綁定參數(shù)時,會將數(shù)據(jù)由 Java 類型轉換成 JDBC 類型;在映射結果集時,會將數(shù)據(jù)由 JDBC 類型轉換成 Java 類型。

  • 日志模塊

在 Java 中,有很多優(yōu)秀的日志框架,如 Log4j、Log4j2、slf4j 等。Mybatis 除了提供了詳細的日志輸出信息,還能夠集成多種日志框架,其日志模塊的主要功能就是集成第三方日志框架。

  • 資源加載模塊

該模塊主要封裝了類加載器,確定了類加載器的使用順序,并提供了加載類文件和其它資源文件的功能。

  • 解析器模塊

該模塊有兩個主要功能:一個是封裝了 XPath,為 Mybatis 初始化時解析 mybatis-config.xml配置文件以及映射配置文件提供支持;另一個為處理動態(tài) SQL 語句中的占位符提供支持。

  • 數(shù)據(jù)源模塊

Mybatis 自身提供了相應的數(shù)據(jù)源實現(xiàn),也提供了與第三方數(shù)據(jù)源集成的接口。數(shù)據(jù)源是開發(fā)中的常用組件之一,很多開源的數(shù)據(jù)源都提供了豐富的功能,如連接池、檢測連接狀態(tài)等,選擇性能優(yōu)秀的數(shù)據(jù)源組件,對于提供ORM 框架以及整個應用的性能都是非常重要的。

  • 事務管理模塊

一般地,Mybatis 與 Spring 框架集成,由 Spring 框架管理事務。但 Mybatis 自身對數(shù)據(jù)庫事務進行了抽象,提供了相應的事務接口和簡單實現(xiàn)。

  • 緩存模塊

Mybatis 中有一級緩存和二級緩存,這兩級緩存都依賴于緩存模塊中的實現(xiàn)。但是需要注意,這兩級緩存與Mybatis 以及整個應用是運行在同一個 JVM 中的,共享同一塊內存,如果這兩級緩存中的數(shù)據(jù)量較大,則可能影響系統(tǒng)中其它功能,所以需要緩存大量數(shù)據(jù)時,優(yōu)先考慮使用 Redis、Memcache 等緩存產(chǎn)品。

  • Binding 模塊

在調用 SqlSession 相應方法執(zhí)行數(shù)據(jù)庫操作時,需要制定映射文件中定義的 SQL 節(jié)點,如果 SQL 中出現(xiàn)了拼寫錯誤,那就只能在運行時才能發(fā)現(xiàn)。為了能盡早發(fā)現(xiàn)這種錯誤,Mybatis 通過 Binding 模塊將用戶自定義的Mapper 接口與映射文件關聯(lián)起來,系統(tǒng)可以通過調用自定義 Mapper 接口中的方法執(zhí)行相應的 SQL 語句完成數(shù)據(jù)庫操作,從而避免上述問題。注意,在開發(fā)中,我們只是創(chuàng)建了 Mapper 接口,而并沒有編寫實現(xiàn)類,這是因為 Mybatis 自動為 Mapper 接口創(chuàng)建了動態(tài)代理對象。

MyBatis 核心組件

在認識了 MyBatis 并了解其基礎架構之后,下面我們來看一下 MyBatis 的核心組件,就是這些組件實現(xiàn)了從 SQL 語句到映射到 JDBC 再到數(shù)據(jù)庫字段之間的轉換,執(zhí)行 SQL 語句并輸出結果集。首先來認識 MyBatis 的第一個核心組件

SqlSessionFactory

對于任何框架而言,在使用該框架之前都要經(jīng)歷過一系列的初始化流程,MyBatis 也不例外。MyBatis 的初始化流程如下

String resource = "org/mybatis/example/mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSessionFactory.openSession();

上述流程中比較重要的一個對象就是SqlSessionFactory,SqlSessionFactory 是 MyBatis 框架中的一個接口,它主要負責的是

  • MyBatis 框架初始化操作
  • 為開發(fā)人員提供SqlSession 對象

SqlSessionFactory 有兩個實現(xiàn)類,一個是 SqlSessionManager 類,一個是 DefaultSqlSessionFactory 類

  • DefaultSqlSessionFactory : SqlSessionFactory 的默認實現(xiàn)類,是真正生產(chǎn)會話的工廠類,這個類的實例的生命周期是全局的,它只會在首次調用時生成一個實例(單例模式),就一直存在直到服務器關閉。
  • SqlSessionManager :已被廢棄,原因大概是: SqlSessionManager 中需要維護一個自己的線程池,而使用MyBatis 更多的是要與 Spring 進行集成,并不會單獨使用,所以維護自己的 ThreadLocal 并沒有什么意義,所以 SqlSessionManager 已經(jīng)不再使用。

SqlSessionFactory 的執(zhí)行流程

下面來對 SqlSessionFactory 的執(zhí)行流程來做一個分析

首先第一步是 SqlSessionFactory 的創(chuàng)建

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

從這行代碼入手,首先創(chuàng)建了一個 SqlSessionFactoryBuilder 工廠,這是一個建造者模式的設計思想,由 builder 建造者來創(chuàng)建 SqlSessionFactory 工廠

然后調用 SqlSessionFactoryBuilder 中的 build 方法傳遞一個InputStream 輸入流,Inputstream 輸入流中就是你傳過來的配置文件 mybatis-config.xml,SqlSessionFactoryBuilder 根據(jù)傳入的 InputStream 輸入流和environment、properties屬性創(chuàng)建一個XMLConfigBuilder對象。SqlSessionFactoryBuilder 對象調用XMLConfigBuilder 的parse()方法,流程如下。

XMLConfigBuilder 會解析/configuration標簽,configuration 是 MyBatis 中最重要的一個標簽,下面流程會介紹 Configuration 標簽。

MyBatis 默認使用 XPath 來解析標簽,關于 XPath 的使用,參見 https://www.w3school.com.cn/xpath/index.asp

在 parseConfiguration 方法中,會對各個在 /configuration 中的標簽進行解析

重要配置

說一下這些標簽都是什么意思吧

  • properties,外部屬性,這些屬性都是可外部配置且可動態(tài)替換的,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞。

一般用來給 environment 標簽中的 dataSource 賦值

還可以通過外部屬性進行配置,但是我們這篇文章以原理為主,不會介紹太多應用層面的操作。

  • settings ,MyBatis 中極其重要的配置,它們會改變 MyBatis 的運行時行為。

settings 中配置有很多,具體可以參考 https://mybatis.org/mybatis-3/zh/configuration.html#settings 詳細了解。這里介紹幾個平常使用過程中比較重要的配置

  • typeAliases,類型別名,類型別名是為 Java 類型設置的一個名字。它只和 XML 配置有關。

當這樣配置時,Blog 可以用在任何使用 domain.blog.Blog 的地方。

  • typeHandlers,類型處理器,無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數(shù)時,還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。

在 org.apache.ibatis.type 包下有很多已經(jīng)實現(xiàn)好的 TypeHandler,可以參考如下

你可以重寫類型處理器或創(chuàng)建你自己的類型處理器來處理不支持的或非標準的類型。

具體做法為:實現(xiàn) org.apache.ibatis.type.TypeHandler 接口, 或繼承一個很方便的類 org.apache.ibatis.type.BaseTypeHandler, 然后可以選擇性地將它映射到一個 JDBC 類型。

  • objectFactory,對象工廠,MyBatis 每次創(chuàng)建結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數(shù)映射存在的時候通過參數(shù)構造方法來實例化。如果想覆蓋對象工廠的默認行為,則可以通過創(chuàng)建自己的對象工廠來實現(xiàn)。
public class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return super.create(type); } public Object create(Class type, List constructorArgTypes, List constructorArgs) { return super.create(type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { super.setProperties(properties); } public boolean isCollection(Class type) { return Collection.class.isAssignableFrom(type); }}

然后需要在 XML 中配置此對象工廠

  • plugins,插件開發(fā),插件開發(fā)是 MyBatis 設計人員給開發(fā)人員留給自行開發(fā)的接口,MyBatis 允許你在已映射語句執(zhí)行過程中的某一點進行攔截調用。MyBatis 允許使用插件來攔截的方法調用包括:Executor、ParameterHandler、ResultSetHandler、StatementHandler 接口,這幾個接口也是 MyBatis 中非常重要的接口,我們下面會詳細介紹這幾個接口。
  • environments,MyBatis 環(huán)境配置,MyBatis 可以配置成適應多種環(huán)境,這種機制有助于將 SQL 映射應用于多種數(shù)據(jù)庫之中。例如,開發(fā)、測試和生產(chǎn)環(huán)境需要有不同的配置;或者想在具有相同 Schema 的多個生產(chǎn)數(shù)據(jù)庫中 使用相同的 SQL 映射。
  • 這里注意一點,雖然 environments 可以指定多個環(huán)境,但是SqlSessionFactory 只能有一個,為了指定創(chuàng)建哪種環(huán)境,只要將它作為可選的參數(shù)傳遞給 SqlSessionFactoryBuilder 即可。
  • databaseIdProvider ,數(shù)據(jù)庫廠商標示,MyBatis 可以根據(jù)不同的數(shù)據(jù)庫廠商執(zhí)行不同的語句,這種多廠商的支持是基于映射語句中的 databaseId 屬性。
  • mappers,映射器,這是告訴 MyBatis 去哪里找到這些 SQL 語句,mappers 映射配置有四種方式

上面的一個個屬性都對應著一個解析方法,都是使用 XPath 把標簽進行解析,解析完成后返回一個 DefaultSqlSessionFactory 對象,它是 SqlSessionFactory 的默認實現(xiàn)類。這就是 SqlSessionFactoryBuilder 的初始化流程,通過流程我們可以看到,初始化流程就是對一個個 /configuration 標簽下子標簽的解析過程。

SqlSession

在 MyBatis 初始化流程結束,也就是 SqlSessionFactoryBuilder -> SqlSessionFactory 的獲取流程后,我們就可以通過 SqlSessionFactory 對象得到 SqlSession 然后執(zhí)行 SQL 語句了。具體來看一下這個過程

在 SqlSessionFactory.openSession 過程中我們可以看到,會調用到 DefaultSqlSessionFactory 中的 openSessionFromDataSource 方法,這個方法主要創(chuàng)建了兩個與我們分析執(zhí)行流程重要的對象,一個是 Executor 執(zhí)行器對象,一個是 SqlSession 對象。執(zhí)行器我們下面會說,現(xiàn)在來說一下 SqlSession 對象

SqlSession 對象是 MyBatis 中最重要的一個對象,這個接口能夠讓你執(zhí)行命令,獲取映射,管理事務。SqlSession 中定義了一系列模版方法,讓你能夠執(zhí)行簡單的 CRUD 操作,也可以通過 getMapper 獲取 Mapper 層,執(zhí)行自定義 SQL 語句,因為 SqlSession 在執(zhí)行 SQL 語句之前是需要先開啟一個會話,涉及到事務操作,所以還會有 commit、 rollback、close 等方法。這也是模版設計模式的一種應用。

MapperProxy

MapperProxy 是 Mapper 映射 SQL 語句的關鍵對象,我們寫的 Dao 層或者 Mapper 層都是通過 MapperProxy 來和對應的 SQL 語句進行綁定的。下面我們就來解釋一下綁定過程

這就是 MyBatis 的核心綁定流程,我們可以看到 SqlSession 首先調用 getMapper 方法,我們剛才說到 SqlSession 是大哥級別的人物,只定義標準(有一句話是怎么說的來著,一流的企業(yè)做標準,二流的企業(yè)做品牌,三流的企業(yè)做產(chǎn)品)。

SqlSession 不愿意做的事情交給 Configuration 這個手下去做,但是 Configuration 也是有小弟的,它不愿意做的事情直接甩給小弟去做,這個小弟是誰呢?它就是 MapperRegistry,馬上就到核心部分了。MapperRegistry 相當于項目經(jīng)理,項目經(jīng)理只從大面上把握項目進度,不需要知道手下的小弟是如何工作的,把任務完成了就好。最終真正干活的還是 MapperProxyFactory。

也就是說,MyBatis 中 Mapper 和 SQL 語句的綁定正是通過動態(tài)代理來完成的。

通過動態(tài)代理,我們就可以方便的在 Dao 層或者 Mapper 層定義接口,實現(xiàn)自定義的增刪改查操作了。那么具體的執(zhí)行過程是怎么樣呢?上面只是綁定過程,別著急,下面就來探討一下 SQL 語句的執(zhí)行過程。

有一部分代碼被遮擋,代碼有些多,不過不影響我們看主要流程

MapperProxyFactory 會生成代理對象,這個對象就是 MapperProxy,最終會調用到 mapperMethod.execute 方法,execute 方法比較長,其實邏輯比較簡單,就是判斷是 插入、更新、刪除 還是 查詢 語句,其中如果是查詢的話,還會判斷返回值的類型,我們可以點進去看一下都是怎么設計的。

很多代碼其實可以忽略,只看我標出來的重點就好了,我們可以看到,不管你前面經(jīng)過多少道關卡處理,最終都逃不過 SqlSession 這個老大制定的標準。

我們以 selectList 為例,來看一下下面的執(zhí)行過程。

這是 DefaultSqlSession 中 selectList 的代碼,我們可以看到出現(xiàn)了 executor,這是什么呢?我們下面來解釋。

Executor

還記得我們之前的流程中提到了 Executor(執(zhí)行器) 這個概念嗎?我們來回顧一下它第一次出現(xiàn)的位置。

由 Configuration 對象創(chuàng)建了一個 Executor 對象,這個 Executor 是干嘛的呢?下面我們就來認識一下

Executor 的繼承結構

每一個 SqlSession 都會擁有一個 Executor 對象,這個對象負責增刪改查的具體操作,我們可以簡單的將它理解為 JDBC 中 Statement 的封裝版。也可以理解為 SQL 的執(zhí)行引擎,要干活總得有一個發(fā)起人吧,可以把 Executor 理解為發(fā)起人的角色。

首先先從 Executor 的繼承體系來認識一下

如上圖所示,位于繼承體系最頂層的是 Executor 執(zhí)行器,它有兩個實現(xiàn)類,分別是BaseExecutor和 CachingExecutor。

BaseExecutor 是一個抽象類,這種通過抽象的實現(xiàn)接口的方式是適配器設計模式之接口適配 的體現(xiàn),是Executor 的默認實現(xiàn),實現(xiàn)了大部分 Executor 接口定義的功能,降低了接口實現(xiàn)的難度。BaseExecutor 的子類有三個,分別是 SimpleExecutor、ReuseExecutor 和 BatchExecutor。

SimpleExecutor : 簡單執(zhí)行器,是 MyBatis 中默認使用的執(zhí)行器,每執(zhí)行一次 update 或 select,就開啟一個Statement 對象,用完就直接關閉 Statement 對象(可以是 Statement 或者是 PreparedStatment 對象)

ReuseExecutor : 可重用執(zhí)行器,這里的重用指的是重復使用 Statement,它會在內部使用一個 Map 把創(chuàng)建的Statement 都緩存起來,每次執(zhí)行 SQL 命令的時候,都會去判斷是否存在基于該 SQL 的 Statement 對象,如果存在 Statement 對象并且對應的 connection 還沒有關閉的情況下就繼續(xù)使用之前的 Statement 對象,并將其緩存起來。因為每一個 SqlSession 都有一個新的 Executor 對象,所以我們緩存在 ReuseExecutor 上的 Statement作用域是同一個 SqlSession。

BatchExecutor : 批處理執(zhí)行器,用于將多個 SQL 一次性輸出到數(shù)據(jù)庫

CachingExecutor: 緩存執(zhí)行器,先從緩存中查詢結果,如果存在就返回之前的結果;如果不存在,再委托給Executor delegate 去數(shù)據(jù)庫中取,delegate 可以是上面任何一個執(zhí)行器。

Executor 的創(chuàng)建和選擇

我們上面提到 Executor 是由 Configuration 創(chuàng)建的,Configuration 會根據(jù)執(zhí)行器的類型創(chuàng)建,如下

這一步就是執(zhí)行器的創(chuàng)建過程,根據(jù)傳入的 ExecutorType 類型來判斷是哪種執(zhí)行器,如果不指定 ExecutorType ,默認創(chuàng)建的是簡單執(zhí)行器。它的賦值可以通過兩個地方進行賦值:

  • 可以通過標簽來設置當前工程中所有的 SqlSession 對象使用默認的 Executor
  • 另外一種直接通過Java對方法賦值的方式
session = factory.openSession(ExecutorType.BATCH);

Executor 的具體執(zhí)行過程

Executor 中的大部分方法的調用鏈其實是差不多的,下面是深入源碼分析執(zhí)行過程,如果你沒有時間或者暫時不想深入研究的話,給你下面的執(zhí)行流程圖作為參考。

我們緊跟著上面的 selectList 繼續(xù)分析,它會調用到 executor.query 方法。

當有一個查詢請求訪問的時候,首先會經(jīng)過 Executor 的實現(xiàn)類 CachingExecutor ,先從緩存中查詢 SQL 是否是第一次執(zhí)行,如果是第一次執(zhí)行的話,那么就直接執(zhí)行 SQL 語句,并創(chuàng)建緩存,如果第二次訪問相同的 SQL 語句的話,那么就會直接從緩存中提取。

上面這段代碼是從 selectList -> 從緩存中 query 的具體過程。可能你看到這里有些覺得類都是什么東西,我想鼓勵你一下,把握重點,不用每段代碼都看,從找到 SQL 的調用鏈路,其他代碼想看的時候在看,看源碼就是很容易發(fā)蒙,容易煩躁,但是切記一點,把握重點。

上面代碼會判斷緩存中是否有這條 SQL 語句的執(zhí)行結果,如果沒有的話,就再重新創(chuàng)建 Executor 執(zhí)行器執(zhí)行 SQL 語句,注意, list = doQuery 是真正執(zhí)行 SQL 語句的過程,這個過程中會創(chuàng)建我們上面提到的三種執(zhí)行器,這里我們使用的是簡單執(zhí)行器。

到這里,執(zhí)行器所做的工作就完事了,Executor 會把后續(xù)的工作交給 StatementHandler 繼續(xù)執(zhí)行。下面我們來認識一下 StatementHandler

StatementHandler

StatementHandler 是四大組件中最重要的一個對象,負責操作 Statement 對象與數(shù)據(jù)庫進行交互,在工作時還會使用 ParameterHandler 和 ResultSetHandler對參數(shù)進行映射,對結果進行實體類的綁定,這兩個組件我們后面說。

我們在搭建原生 JDBC 的時候,會有這樣一行代碼

Statement stmt = conn.createStatement(); //也可以使用PreparedStatement來做

這行代碼創(chuàng)建的 Statement 對象或者是 PreparedStatement 對象就是由 StatementHandler 進行管理的。

StatementHandler 的繼承結構

有沒有感覺和 Executor 的繼承體系很相似呢?最頂級接口是四大組件對象,分別有兩個實現(xiàn)類 BaseStatementHandler 和 RoutingStatementHandler,BaseStatementHandler 有三個實現(xiàn)類, 他們分別是 SimpleStatementHandler、PreparedStatementHandler 和 CallableStatementHandler。

RoutingStatementHandler : RoutingStatementHandler 并沒有對 Statement 對象進行使用,只是根據(jù)StatementType 來創(chuàng)建一個代理,代理的就是對應Handler的三種實現(xiàn)類。在MyBatis工作時,使用的StatementHandler 接口對象實際上就是 RoutingStatementHandler 對象。

BaseStatementHandler : 是 StatementHandler 接口的另一個實現(xiàn)類,它本身是一個抽象類,用于簡化StatementHandler 接口實現(xiàn)的難度,屬于適配器設計模式體現(xiàn),它主要有三個實現(xiàn)類

  • SimpleStatementHandler: 管理 Statement 對象并向數(shù)據(jù)庫中推送不需要預編譯的SQL語句。
  • PreparedStatementHandler: 管理 Statement 對象并向數(shù)據(jù)中推送需要預編譯的SQL語句。
  • CallableStatementHandler:管理 Statement 對象并調用數(shù)據(jù)庫中的存儲過程。

這里注意一下,SimpleStatementHandler 和 PreparedStatementHandler 的區(qū)別是 SQL 語句是否包含變量,是否通過外部進行參數(shù)傳入。

SimpleStatementHandler 用于執(zhí)行沒有任何參數(shù)傳入的 SQL

PreparedStatementHandler 需要對外部傳入的變量和參數(shù)進行提前參數(shù)綁定和賦值。

StatementHandler 的創(chuàng)建和源碼分析

我們繼續(xù)來分析上面 query 的調用鏈路,StatementHandler 的創(chuàng)建過程如下

MyBatis 會根據(jù) SQL 語句的類型進行對應 StatementHandler 的創(chuàng)建。我們以預處理 StatementHandler 為例來講解一下

執(zhí)行器不僅掌管著 StatementHandler 的創(chuàng)建,還掌管著創(chuàng)建 Statement 對象,設置參數(shù)等,在創(chuàng)建完 PreparedStatement 之后,我們需要對參數(shù)進行處理了。

如果用一副圖來表示一下這個執(zhí)行流程的話我想是這樣

這里我們先暫停一下,來認識一下第三個核心組件 ParameterHandler

ParameterHandler

ParameterHandler 介紹

ParameterHandler 相比于其他的組件就簡單很多了,ParameterHandler 譯為參數(shù)處理器,負責為 PreparedStatement 的 sql 語句參數(shù)動態(tài)賦值,這個接口很簡單只有兩個方法

ParameterHandler 只有一個實現(xiàn)類 DefaultParameterHandler , 它實現(xiàn)了這兩個方法。

  • getParameterObject:用于讀取參數(shù)
  • setParameters: 用于對 PreparedStatement 的參數(shù)賦值

ParameterHandler 的解析過程

上面我們討論過了 ParameterHandler 的創(chuàng)建過程,下面我們繼續(xù)上面 parameterSize 流程

這就是具體參數(shù)的解析過程了,下面我們來描述一下

public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); // parameterMappings 就是對 #{} 或者 ${} 里面參數(shù)的封裝 List parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { // 如果是參數(shù)化的SQL,便需要循環(huán)取出并設置參數(shù)的值 for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); // 如果參數(shù)類型不是 OUT ,這個類型與 CallableStatementHandler 有關 // 因為存儲過程不存在輸出參數(shù),所以參數(shù)不是輸出參數(shù)的時候,就需要設置。 if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; // 得到 #{} 中的屬性名 String propertyName = parameterMapping.getProperty(); // 如果 propertyName 是 Map 中的key if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params // 通過key 來得到 additionalParameter 中的value值 value = boundSql.getAdditionalParameter(propertyName); } // 如果不是 additionalParameters 中的key,而且傳入?yún)?shù)是 null, 則value 就是null else if (parameterObject == null) { value = null; } // 如果 typeHandlerRegistry 中已經(jīng)注冊了這個參數(shù)的 Class 對象,即它是 Primitive 或者是String 的話 else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { // 否則就是 Map MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } // 在通過 SqlSource 的parse 方法得到parameterMappings 的具體實現(xiàn)中,我們會得到parameterMappings 的 typeHandler TypeHandler typeHandler = parameterMapping.getTypeHandler(); // 獲取 typeHandler 的jdbc type JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } catch (SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } }}

下面用一個流程圖表示一下 ParameterHandler 的解析過程,以簡單執(zhí)行器為例

我們在完成 ParameterHandler 對 SQL 參數(shù)的預處理后,回到 SimpleExecutor 中的 doQuery 方法

上面又引出來了一個重要的組件那就是 ResultSetHandler,下面我們來認識一下這個組件

ResultSetHandler

ResultSetHandler 簡介

ResultSetHandler 也是一個非常簡單的接口

ResultSetHandler 是一個接口,它只有一個默認的實現(xiàn)類,像是 ParameterHandler 一樣,它的默認實現(xiàn)類是DefaultResultSetHandler

ResultSetHandler 解析過程

MyBatis 只有一個默認的實現(xiàn)類就是 DefaultResultSetHandler,DefaultResultSetHandler 主要負責處理兩件事

  • 處理 Statement 執(zhí)行后產(chǎn)生的結果集,生成結果列表
  • 處理存儲過程執(zhí)行后的輸出參數(shù)

按照 Mapper 文件中配置的 ResultType 或 ResultMap 來封裝成對應的對象,最后將封裝的對象返回即可。

public List handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); final List multipleResults = new ArrayList(); int resultSetCount = 0; // 獲取第一個結果集 ResultSetWrapper rsw = getFirstResultSet(stmt); // 獲取結果映射 List resultMaps = mappedStatement.getResultMaps(); // 結果映射的大小 int resultMapCount = resultMaps.size(); // 校驗結果映射的數(shù)量 validateResultMapsCount(rsw, resultMapCount); // 如果ResultSet 包裝器不是null, 并且 resultmap 的數(shù)量 > resultSet 的數(shù)量的話 // 因為 resultSetCount 第一次肯定是0,所以直接判斷 ResultSetWrapper 是否為 0 即可 while (rsw != null && resultMapCount > resultSetCount) { // 從 resultMap 中取出 resultSet 數(shù)量 ResultMap resultMap = resultMaps.get(resultSetCount); // 處理結果集, 關閉結果集 handleResultSet(rsw, resultMap, multipleResults, null); rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } // 從 mappedStatement 取出結果集 String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults);}

其中涉及的主要對象有:

ResultSetWrapper : 結果集的包裝器,主要針對結果集進行的一層包裝,它的主要屬性有

  • ResultSet : Java JDBC ResultSet 接口表示數(shù)據(jù)庫查詢的結果。有關查詢的文本顯示了如何將查詢結果作為java.sql.ResultSet 返回。然后迭代此ResultSet以檢查結果。
  • TypeHandlerRegistry: 類型注冊器,TypeHandlerRegistry 在初始化的時候會把所有的 Java類型和類型轉換器進行注冊。
  • ColumnNames: 字段的名稱,也就是查詢操作需要返回的字段名稱
  • ClassNames: 字段的類型名稱,也就是 ColumnNames 每個字段名稱的類型
  • JdbcTypes: JDBC 的類型,也就是 java.sql.Types 類型
  • ResultMap: 負責處理更復雜的映射關系

在 DefaultResultSetHandler 中處理完結果映射,并把上述結構返回給調用的客戶端,從而執(zhí)行完成一條完整的SQL語句。

總結

以上是生活随笔為你收集整理的java执行sql文件_面试官:MyBatis SQL是如何执行的?把这篇文章甩给他的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。

五月情婷婷 | 亚洲精品久久久久999中文字幕 | 97视频免费在线 | 日韩网页 | 国产日韩在线观看一区 | 插久久| 在线观看中文 | 国产精品成人一区二区 | 婷婷在线网| 综合网在线视频 | 在线视频区| 国产福利av | 9热精品| 在线观看亚洲视频 | 亚洲精品国偷自产在线91正片 | 伊人天天狠天天添日日拍 | 日韩av成人在线观看 | 日韩免费视频在线观看 | 91在线最新| 96亚洲精品久久 | 成人午夜影视 | 国语自产偷拍精品视频偷 | 91综合视频在线观看 | 一级成人网 | 97超碰免费在线 | av福利在线免费观看 | 国产精品久久久av | 欧美 日韩精品 | 国产视频精品久久 | 日韩综合视频在线观看 | 天天色天天综合网 | 国产精品久久麻豆 | 黄色小网站免费看 | 久久婷婷精品视频 | 国产精品岛国久久久久久久久红粉 | 精品久久久久久亚洲 | 午夜精品久久久久久中宇69 | 欧日韩在线视频 | 成人国产精品免费观看 | 一级做a爱片性色毛片www | 亚洲人在线 | 欧美疯狂性受xxxxx另类 | 欧美日韩高清在线观看 | 久久精品香蕉视频 | 国产精品久久在线观看 | 亚洲va在线va天堂 | 久99久精品 | 国产精品久久久视频 | 超碰人人乐 | 精品极品在线 | 国产成人免费av电影 | 婷婷综合av | 亚洲视频免费在线观看 | 亚洲综合网站在线观看 | 久久精品视频在线免费观看 | 日韩在线高清免费视频 | 日韩精品久久一区二区三区 | 一区二区三区四区五区在线 | 欧美日韩精品在线一区二区 | 在线观看日韩免费视频 | 久久精品中文视频 | 国产亚洲在线视频 | 亚洲综合涩 | 午夜国产福利视频 | 久久私人影院 | 国产一级二级在线播放 | 人人爽影院 | 日韩欧美在线不卡 | 国产精品美女久久久久久2018 | 夜夜干夜夜 | 国产精品九九久久久久久久 | 91久久黄色| 999在线观看视频 | 九色在线 | 久久经典视频 | 干干操操 | 久久免费视频这里只有精品 | 久久久精品99 | 在线观看av不卡 | 久久综合五月天婷婷伊人 | 色综合五月天 | 欧美一区二区三区特黄 | 亚洲欧美日韩精品久久久 | www.天天射| 国产一区二区在线影院 | 日韩精选在线观看 | 国产亚洲情侣一区二区无 | 在线观看色网 | 国产精品91一区 | 99国产在线视频 | 99久久久久久国产精品 | av福利免费| 国内精品福利视频 | 日韩激情视频 | 六月丁香社区 | 国产一级电影 | 国产精品专区h在线观看 | 91精品1区2区 | 久久久久一区二区三区 | 美女视频一区 | 久草在线免费新视频 | 在线观看深夜视频 | 久久免费视频在线观看 | 成人va视频| 九九久久国产精品 | 久久污视频 | 69精品视频 | 国产成人一区二区三区影院在线 | 日韩在线首页 | 午夜99| 成人免费视频视频在线观看 免费 | 国产99久久九九精品免费 | 91丨porny丨九色| 久久精品视频99 | 日韩精品视频一二三 | 日韩欧美精品在线视频 | 涩涩在线 | 蜜臀一区二区三区精品免费视频 | 麻豆成人小视频 | 美女视频永久黄网站免费观看国产 | 日韩午夜在线观看 | 中文字幕在线观看视频一区二区三区 | 中文字幕传媒 | 13日本xxxxxⅹxxx20 | 亚洲天天做 | 99久久er热在这里只有精品66 | 99视频免费播放 | 国产麻豆精品在线观看 | 婷婷亚洲激情 | 国产午夜一级毛片 | 亚洲精品mv在线观看 | 久久免费的精品国产v∧ | 国产69精品久久app免费版 | 国产一区二区精品在线 | 日本不卡一区二区三区在线观看 | av片子在线观看 | 色视频在线观看免费 | 在线欧美日韩 | 在线看av的网址 | 国产97在线视频 | 最新日韩中文字幕 | 日本精品视频在线观看 | 国产精品毛片久久蜜 | 久久久精品免费观看 | www99久久 | 欧美日韩视频一区二区 | 又黄又爽免费视频 | 91成人久久 | 中文字幕在线高清 | 91在线色 | 色中色亚洲 | 日韩精品久久久免费观看夜色 | 国产成人高清av | 久久精品国产免费看久久精品 | 久久综合操 | 亚洲视频在线观看 | 国产精久久久久久妇女av | 伊人五月婷 | 国产成人av电影 | 91亚州| 97精品超碰一区二区三区 | 国产剧情一区在线 | 五月婷婷色综合 | 亚洲天堂首页 | 国产精品免费大片视频 | 在线观看国产区 | 欧美一区视频 | 天天操天天操天天操天天 | 91精品国产91久久久久福利 | 天天操夜夜逼 | 亚洲国内精品 | 国产精品国产三级国产 | 亚洲精品国产精品国自产在线 | 一区二区 不卡 | 久久天天躁狠狠躁亚洲综合公司 | 中文字幕中文字幕在线中文字幕三区 | 亚洲精品国产精品国自产 | 国产精品久久久一区二区三区网站 | 精品九九九九 | 五月婷婷丁香 | 欧美日韩中文在线观看 | 国产精品久久久免费 | 91禁看片 | 91精品一区在线观看 | 国产一级片免费观看 | 久热免费在线 | 国产原厂视频在线观看 | 久久激情五月丁香伊人 | 日韩免费专区 | 日本中文字幕系列 | 69国产精品视频免费观看 | 日韩av电影免费观看 | 国产精品18久久久久久久 | 亚洲国产精品999 | 久久精品免费观看 | 久久久久亚洲精品 | 亚洲欧美色婷婷 | 欧美国产高清 | 日本精品视频一区 | 手机成人在线电影 | 天天操天天操天天 | 婷婷社区五月天 | bayu135国产精品视频 | 黄色动态图xx | 国产精品不卡在线观看 | 天天草天天 | 欧美精品一二三 | 一区三区在线欧 | 国产精品夜夜夜一区二区三区尤 | av免费在线网 | www.玖玖玖| 91成年视频 | www.黄色片网站| 在线观看的a站 | 国产高清中文字幕 | www.激情五月.com| 国产精品久久久亚洲 | 午夜免费在线观看 | 极品久久久久久久 | www.午夜 | 国产最新在线视频 | 91理论片午午伦夜理片久久 | 国产精品成人自产拍在线观看 | 亚洲黄色片| 手机成人av | 欧美一区免费观看 | 中文字幕电影一区 | 久久久久久国产精品 | 久久国产精品一二三区 | 国产精品久久99精品毛片三a | 91av小视频| 精品久久免费 | 99久久久久免费精品国产 | 亚洲一级久久 | 亚洲精品国产精品乱码不99热 | 在线免费观看亚洲视频 | 国产一区欧美二区 | 91视视频在线直接观看在线看网页在线看 | 欧美久久久久久久久久久 | 免费看片网页 | 国产美女在线观看 | 特黄特色特刺激视频免费播放 | 久久久久久蜜av免费网站 | 欧美在线观看小视频 | 成人免费毛片aaaaaa片 | 在线视频 你懂得 | 91av大全 | 久久午夜电影院 | 91正在播放 | 欧美成a人片在线观看久 | 视频福利在线观看 | 日韩色av色资源 | 日本精品久久久一区二区三区 | 亚洲精品中文字幕在线 | 国产美女在线免费观看 | 少妇搡bbbb搡bbb搡69 | 久久在线免费观看视频 | 在线播放视频一区 | 1024手机在线看 | 国产精品网在线观看 | 国产视频日韩视频欧美视频 | 欧美老人xxxx18 | 五月婷网站 | 99精品在线免费视频 | 亚洲国产精品99久久久久久久久 | www.久草.com | 久久韩国免费视频 | 最新中文字幕在线播放 | 中文字幕成人网 | 天天干,天天干 | 色婷婷97 | 久久黄色免费视频 | 国产精品自在线 | 在线视频观看亚洲 | 免费v片| 日韩av午夜在线观看 | 久久久久久久网站 | 狠狠干天天干 | 日韩在线 一区二区 | 91大神电影 | 久久这里只有精品视频首页 | 免费在线看v | 国产精品成人自产拍在线观看 | 97精品久久 | 国产视频在线观看一区二区 | 国内精品视频久久 | 亚洲一区视频在线播放 | 色资源在线观看 | 一区二区三区精品久久久 | 久久艹艹 | 中文字幕免费一区 | 久久99婷婷| 国产精品免费一区二区三区在线观看 | av免费看在线 | 成x99人av在线www | 国产精品成人久久 | 天堂在线视频中文网 | 久久精品一区二区三区中文字幕 | 成人福利在线观看 | 久久五月婷婷丁香 | 激情综合站 | 亚洲国产精品久久久久婷婷884 | 日韩免费电影一区二区三区 | 精品国产乱码久久久久久浪潮 | 日韩在线播放av | 亚洲国产精品视频在线观看 | 欧美在线观看视频免费 | 91精品视频免费看 | 99精品免费 | 色中色亚洲 | 成人黄视频 | a在线观看免费视频 | 色999在线 | 97在线精品国自产拍中文 | 久久人人爽人人爽人人片av软件 | 久久性生活片 | 国产精品欧美久久久久久 | 97在线播放视频 | 成人av网页 | 51久久夜色精品国产麻豆 | 五月香视频在线观看 | 亚洲精品va| 亚洲精品午夜一区人人爽 | 91在线视频免费观看 | 欧美精品亚洲二区 | 97成人精品区在线播放 | 日韩 国产 | 亚洲综合精品在线 | 久久成人国产精品免费软件 | 人人干人人草 | 天天躁日日 | 久久久午夜视频 | 国产免费大片 | 五月天视频网 | 中文字幕在线免费观看 | 中文字幕一二 | 亚洲第一伊人 | 国内精品久久久久久中文字幕 | 中文字幕免费一区二区 | 97精品国产手机 | 亚洲成免费 | 色噜噜狠狠色综合中国 | av大全在线免费观看 | 色婷婷久久久综合中文字幕 | 国产99久久久国产精品免费二区 | 国产精品一区二区三区久久久 | 欧美一区二区三区免费看 | 天天插天天 | 久草在在线视频 | 日本在线视频网址 | 天天爽天天碰狠狠添 | 国产专区第一页 | 超碰97人人干 | 中文视频在线播放 | 97精品国产一二三产区 | 九月婷婷人人澡人人添人人爽 | 99在线热播精品免费 | 国产亚洲精品bv在线观看 | 天天色综合1| 区一区二区三区中文字幕 | 久久成人国产精品免费软件 | 国产99久久 | 亚洲免费av在线 | 91一区啪爱嗯打偷拍欧美 | 狠狠色香婷婷久久亚洲精品 | 看片的网址 | 国产精品一区二区你懂的 | 精品国产一区二区三区不卡 | 国产精品亚洲视频 | 日韩视频中文字幕 | 中文字幕在线观看第一区 | 天天操天天操天天操天天操天天操 | 黄色三级网站 | 操操爽| 国产亚州精品视频 | 色婷婷骚婷婷 | 深爱激情开心 | ww亚洲ww亚在线观看 | 精品亚洲欧美一区 | 中文字幕在线播放一区二区 | 日本精品一区二区 | 国产亚洲人 | 韩国av免费 | 超碰在线97免费 | 国产视频精品久久 | 香蕉视频网站在线观看 | 欧美激情精品久久久久久免费 | 伊人伊成久久人综合网站 | 91片黄在线观 | 精品资源在线 | 婷婷在线网 | 国产xx视频 | 在线免费观看黄网站 | 97视频入口免费观看 | 亚洲在线日韩 | 国产美女在线观看 | 天天干亚洲 | 国产日韩精品一区二区在线观看播放 | 91av观看 | 久久99国产精品免费网站 | 久久国产精品一国产精品 | 日韩欧美综合视频 | 99热国内精品| 婷婷久月 | 99精品视频观看 | 国产在线观看99 | 婷婷激情综合五月天 | 91在线入口 | 国产黄色理论片 | 精品国产91亚洲一区二区三区www | 久久久精品久久日韩一区综合 | 99精品国自产在线 | 欧美性久久久久久 | 一区二区三区三区在线 | 狠狠干天天 | 九九在线国产视频 | 六月色丁香 | 麻花豆传媒mv在线观看网站 | a√资源在线 | 开心色婷婷| 国产一区二区在线视频观看 | 日韩字幕 | 97精品伊人 | 久久久久久久久久影院 | 久久人人看 | 国产高清精 | 婷婷午夜天 | 二区三区中文字幕 | 6080yy精品一区二区三区 | 五月激情丁香 | 国产在线精品一区二区 | 韩日精品中文字幕 | 色噜噜日韩精品欧美一区二区 | 青青草国产成人99久久 | 青青网视频 | 日韩免费一级a毛片在线播放一级 | 色多视频在线观看 | 久久欧美在线电影 | 欧美黄网站 | 日韩精品视频免费在线观看 | 四虎在线观看视频 | 精品一区二区精品 | 91一区啪爱嗯打偷拍欧美 | 亚洲日韩欧美视频 | 日韩视频一区二区在线 | 久久久久久久久亚洲精品 | 黄色片免费看 | 亚洲国产精品电影在线观看 | 亚洲区精品视频 | 亚洲精品午夜久久久久久久久久久 | 免费三及片 | 欧美精品天堂 | 九九欧美 | 九色91视频| 成人网中文字幕 | av丝袜在线 | 奇米影视8888在线观看大全免费 | 亚洲免费在线看 | 激情综合色图 | 福利视频网址 | 国产精品久久久亚洲 | 精品国产乱码久久久久久浪潮 | 亚洲一区二区精品视频 | 69国产盗摄一区二区三区五区 | 亚洲国产小视频在线观看 | 中午字幕在线观看 | 婷婷丁香色综合狠狠色 | 欧美日韩在线观看视频 | 日韩av电影中文字幕 | 亚洲精品国产精品国自产 | 五月婷婷一区 | 狠狠干美女 | 亚洲日本va在线观看 | 国产精品久久免费看 | 天天爱天天操 | 美女视频永久黄网站免费观看国产 | 在线观看第一页 | 99久久精品国产亚洲 | 日色在线视频 | 91视频啪| 久久99热精品这里久久精品 | 天天操天天舔天天干 | 成人97视频| 24小时日本在线www免费的 | 久草在线视频免赞 | 一区二区视频在线观看免费 | 91污在线 | 在线看免费| 亚洲自拍偷拍色图 | 一区二区三区精品久久久 | 色综合天天狠天天透天天伊人 | 91成人免费视频 | 国产传媒一区在线 | 久久免费电影网 | 色悠悠久久综合 | 在线观看韩日电影免费 | 日韩高清免费电影 | 激情网色 | 国产精品久久久久久久久费观看 | 日韩av电影手机在线观看 | 992tv人人草| 日韩在线电影观看 | 午夜精品一区二区三区四区 | 中文字幕一区二区三区精华液 | 国产精品18久久久久久久网站 | 国产在线视频在线观看 | 中文字幕三区 | 免费在线观看中文字幕 | 色综合天天视频在线观看 | 青草草在线 | 国产成人精品综合久久久久99 | 黄色特级毛片 | 天天舔天天射天天操 | 欧美日韩二三区 | 亚洲精品视频在线 | 午夜精品区 | 国产在线不卡视频 | 天天舔天天搞 | 久久免费观看少妇a级毛片 久久久久成人免费 | 国产亚洲精品久久久久久久久久 | 蜜臀一区二区三区精品免费视频 | 中文字幕a∨在线乱码免费看 | 国产成人精品一区二区三区网站观看 | 国内外成人免费在线视频 | 天天色天天干天天色 | 色婷婷国产在线 | 91入口在线观看 | 亚洲成av人影片在线观看 | 欧美午夜精品久久久久久浪潮 | 日日夜夜免费精品视频 | 九色精品免费永久在线 | 又黄又刺激的视频 | 韩国av一区二区三区在线观看 | 玖玖在线播放 | 婷婷综合导航 | 在线观看网站av | 在线视频 区 | 91日韩在线| av大片网址 | 91成人精品一区在线播放69 | 色中文字幕在线观看 | 五月综合在线观看 | 国产专区精品视频 | 中文字幕一区二区三区久久 | 天天摸天天操天天舔 | 91av视频在线观看 | 激情中文在线 | 久久久久伊人 | 日韩av成人在线 | 中文字幕在线视频国产 | 伊人婷婷 | 999久久久免费视频 午夜国产在线观看 | 一区二区视频电影在线观看 | 五月花丁香婷婷 | 不卡的av电影 | 婷婷丁香狠狠爱 | 国产精品99久久久 | 91精品国产福利在线观看 | 成人免费观看视频大全 | 日韩电影在线观看一区 | 久久伊人婷婷 | 黄色福利| 午夜电影中文字幕 | 国产视频2区 | a级一a一级在线观看 | 久久久久久久久久久久久久免费看 | 五月婷婷激情五月 | 国产精品久久久久久久久久了 | 婷婷丁香av | 成人aⅴ视频 | 日日干干| 在线影视 一区 二区 三区 | 夜夜骑日日操 | 国产女教师精品久久av | 亚洲人成网站精品片在线观看 | 久久精品久久久久电影 | 99 久久久久 | 在线观看视频你懂的 | 国产尤物一区二区三区 | 久久经典国产 | 国产精品视频999 | 国产精品电影在线 | 国产高清在线a视频大全 | 狠狠色狠狠色合久久伊人 | 日日夜夜免费精品 | 久久精品中文字幕免费mv | 国产永久免费高清在线观看视频 | 激情综合啪| 美女视频黄是免费的 | 伊人五月 | 国产在线国偷精品产拍 | 九九九热精品免费视频观看网站 | 久久久黄色av | 麻豆成人精品 | 久久久蜜桃一区二区 | 天天干天天看 | 精品久久一二三区 | 青青草国产成人99久久 | 91精品啪在线观看国产81旧版 | 97视频网站| 久久成人国产精品免费软件 | 五月婷婷av | av大全免费在线观看 | 欧美国产91| 91成人亚洲| 色网站中文字幕 | 99热只有精品在线观看 | 久草视频2 | 国产精品久久久久久久婷婷 | 亚洲午夜久久久久久久久 | 亚洲免费精品一区二区 | www黄在线| 狠狠色狠狠色 | 成人av高清在线 | 97人人网 | 亚洲综合欧美日韩狠狠色 | 国产精品毛片网 | 激情影院在线观看 | 国产一二三精品 | 久久久午夜精品理论片中文字幕 | 日本精品中文字幕 | 黄色看片| 欧美精品久久久久性色 | 99热在线这里只有精品 | 黄色电影网站在线观看 | 91亚洲成人 | 亚洲一区动漫 | 国产小视频免费在线网址 | 91av片 | 免费婷婷| 中日韩在线视频 | 久久久久久久久久久黄色 | 国产老妇av | 久久久国产一区二区三区 | 日韩大片在线免费观看 | 精品久久久久久久久久久久 | 成人免费在线网 | 亚洲做受高潮欧美裸体 | 97色综合| 精品成人在线 | 日韩一区二区三区高清在线观看 | 蜜臀aⅴ国产精品久久久国产 | av在线影片| 国产资源网站 | 日韩国产高清在线 | 欧美激情视频一区二区三区免费 | 狠狠色丁香久久综合网 | 美女视频黄是免费的 | 国产精品手机在线 | 美女网站黄在线观看 | 久久综合九色综合欧美就去吻 | 成人h视频| 91色九色| 中国一级片免费看 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 91久久精品日日躁夜夜躁国产 | 中文伊人 | 国产网红在线 | 免费福利在线播放 | 亚洲区精品视频 | 国产精品久久嫩一区二区免费 | 日韩av网址在线 | 久久深夜 | 天天插天天狠 | 亚洲永久字幕 | 91视频免费视频 | 美女免费网站 | 波多野结衣精品视频 | 婷婷中文字幕综合 | 五月激情站| av性在线| 激情导航| 久久视频在线观看 | 日日操操操 | 国产精品成人免费一区久久羞羞 | www.69xx| 69久久久久久久 | 精品麻豆入口免费 | 夜夜夜| 免费看的黄色 | 视频在线日韩 | 午夜精品视频免费在线观看 | 在线黄av | 午夜av一区二区三区 | 日韩性久久 | 亚洲午夜久久久影院 | 久久久久高清毛片一级 | 人人爱爱 | 国产中文字幕视频在线观看 | 9992tv成人免费看片 | 青青久草在线视频 | 粉嫩aⅴ一区二区三区 | 久久精品一区二区三区视频 | 91久久丝袜国产露脸动漫 | av午夜电影| 国产视频一区精品 | 国产午夜亚洲精品 | 91视频免费国产 | 四虎影视成人精品 | 六月丁香激情综合色啪小说 | 久草在线资源网 | 精品在线视频一区二区三区 | 日韩一区二区免费在线观看 | 色爱成人网 | 国产精品毛片久久久久久久 | 成年人免费电影 | 日韩乱色精品一区二区 | 五月天精品视频 | 国产精品嫩草影院9 | 91av综合| 奇米网8888| 97人人模人人爽人人少妇 | 免费观看的黄色 | 国产小视频免费在线网址 | av电影在线观看完整版一区二区 | 色综合在| 欧美日韩中文在线 | 久久久久久久久久免费视频 | 天天射天天干天天操 | 狠狠干狠狠插 | 三级动图 | 右手影院亚洲欧美 | av资源免费看 | 免费av在线播放 | 久久久av免费 | 亚洲免费av网站 | 91精品夜夜 | 中文字幕在线观看av | 六月天综合网 | 久久综合九色综合欧美就去吻 | 91在线观看视频 | 91精品久久久久久综合乱菊 | 精品欧美一区二区在线观看 | 国产精品九色 | 免费色视频网址 | 欧美久久久 | 欧美视频在线观看免费网址 | 韩国av一区二区三区在线观看 | 亚洲综合视频在线观看 | 精品久久网站 | 天天亚洲 | 久久国产精品一区二区三区四区 | 二区三区在线视频 | 中文字幕色在线视频 | 一区二区三区在线视频观看58 | 亚洲欧美一区二区三区孕妇写真 | 美女网站在线看 | 天天综合久久综合 | 日韩高清免费在线观看 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 中文字幕中文字幕中文字幕 | 激情综合久久 | 亚洲国产精品一区二区尤物区 | 99国产一区二区三精品乱码 | 日日夜夜精品免费观看 | 久久人人97超碰精品888 | 果冻av在线| 精久久久久 | 久日精品| 操操操日日日干干干 | 在线观看一区 | 97成人超碰| 精品久久久久久久久中文字幕 | 91亚洲精品国偷拍 | 碰超在线 | 久草在线在线精品观看 | av中文在线影视 | 在线免费观看国产精品 | 成人在线视频免费观看 | 亚洲一区免费在线 | 97电影手机版 | 一区二区三区四区免费视频 | 曰本三级在线 | 亚洲精品视频在线看 | 视频在线日韩 | 亚洲天堂首页 | 国产精品原创 | 国产精品九色 | 日韩高清二区 | 成人在线播放av | 国产欧美日韩精品一区二区免费 | 99国产精品久久久久久久久久 | 欧美一区二区在线刺激视频 | 一区二区三高清 | 五月天.com | 黄色毛片视频免费观看中文 | 成人在线观看资源 | 欧美极品少妇xbxb性爽爽视频 | 人人澡人 | 久草男人天堂 | 久久爽久久爽久久av东京爽 | 91 在线视频 | av网站大全免费 | 最新av免费在线 | 在线免费观看欧美日韩 | 久久久精品欧美 | 91视频免费视频 | 欧美日韩国产精品一区二区 | 亚洲成熟女人毛片在线 | 日日夜夜精品视频天天综合网 | 国产一区二区在线观看免费 | 色播亚洲婷婷 | 久久尤物电影视频在线观看 | 99精品国产一区二区 | 丁香婷婷色综合亚洲电影 | 久久久免费观看视频 | 狠狠的操狠狠的干 | 久久精品久久久久久久 | 亚洲高清在线精品 | 高清一区二区三区 | 91视频在线自拍 | 福利片免费看 | 国产乱码精品一区二区三区介绍 | 黄色成人av在线 | 久久99久久99精品免观看软件 | 国产又粗又猛又黄又爽的视频 | av一区二区三区在线观看 | 成人免费观看视频大全 | 久久99国产视频 | 黄色福利视频网站 | 在线不卡中文字幕播放 | 日韩精品一区二区三区免费观看视频 | 亚州欧美视频 | 亚洲精品综合在线观看 | 91亚色视频 | 国产黄在线| 婷婷色在线 | 中文字幕国产精品 | 久久久久成人精品免费播放动漫 | 狠狠色丁香婷婷综合橹88 | 一区二区三区动漫 | 成人黄色小视频 | 免费看成人a | 精品在线一区二区 | 日本精品一区二区三区在线观看 | 九九色在线| 亚洲精品国产区 | 亚洲一区二区三区91 | 国产午夜激情视频 | 久久精品视频在线看 | 91精品国产自产在线观看 | 五月婷婷综合色拍 | 亚洲国产成人久久 | 亚洲 欧洲 国产 精品 | 国产成人一区在线 | 一区二区三区在线不卡 | 999国产在线 | 不卡电影一区二区三区 | 精品国产精品一区二区夜夜嗨 | 久久久精品在线观看 | 亚洲国产精品传媒在线观看 | 91av在线精品| 亚洲成人精品在线 | 亚洲精品国偷自产在线99热 | 91免费在线播放 | 久久国产免费看 | www免费在线观看 | 992tv在线成人免费观看 | 97人人看| 欧美国产一区在线 | 亚洲伊人第一页 | 亚洲一区二区三区精品在线观看 | 亚洲一区久久久 | 亚洲久草网 | www黄色| 成人一级黄色片 | 九九视频免费在线观看 | 人人爱人人爽 | 中文字幕乱码亚洲精品一区 | 97超碰中文 | 在线国产视频一区 | 日韩精品久久久免费观看夜色 | 亚洲国产合集 | 国产一区电影在线观看 | 免费在线黄色av | 久久艹影院 | 亚洲精品视频一 | 91在线欧美 | 91视频这里只有精品 | 国内少妇自拍视频一区 | 久久精品99| 欧美性视频网站 | 91麻豆精品国产91久久久无需广告 | 国产啊v在线 | 九九九视频在线 | 日韩免费一区二区在线观看 | 久久精品黄| 久久久久久久18 | 国产剧情久久 | 天天操天天透 | 亚洲欧美日韩国产一区二区三区 | 夜夜看av | 91成人在线观看高潮 | 亚洲国产成人精品久久 | 国产精品久久影院 | 日本久久成人中文字幕电影 | 麻豆视频在线免费 | www.黄色片网站 | 国产99久久精品 | 五月天天色 | 精品国产欧美一区二区三区不卡 | 人人干人人干人人干 | 成人午夜精品福利免费 | 亚洲精品乱码久久久久久蜜桃91 | 国产精品免费人成网站 | 午夜在线免费视频 | a级一a一级在线观看 | 国产午夜小视频 | 精品五月天| 精品国产一区二区三区久久久蜜臀 | 97超碰人人干 | 少妇搡bbbb搡bbb搡69 | 免费在线观看的av网站 | 色爱区综合激月婷婷 | 99久久久久久 | 黄色国产区 | 国产精品尤物视频 | 91大神精品视频在线观看 | 亚洲视频免费在线看 | 99精品免费久久久久久久久日本 | 另类老妇性bbwbbw高清 | www.色爱 | av成人免费在线观看 | 中文字幕在线观看不卡 | 婷婷视频在线观看 | 99视| 黄色毛片一级 | 搡bbbb搡bbb视频 | 久久99在线观看 | 一区二区精品视频 | 99久久精品国产系列 | 91人人爽人人爽人人精88v | 97视频播放 | 97精品国产97久久久久久免费 | 国产精品免费视频观看 | 人人爱人人做人人爽 | 欧美日韩在线精品一区二区 | 国产主播大尺度精品福利免费 | 伊人成人精品 | av短片在线观看 | 尤物一区二区三区 | 亚洲免费公开视频 | 四虎影视成人精品国库在线观看 | 免费人成在线观看 | 亚洲精品色视频 | 美女久久久久久久 | 91视频传媒 | 国产高清av| 91免费网址 | 久草在线欧美 | 久草在线观看 | av一区二区三区在线 | av手机版 | 久久精品久久99 | 久久久综合九色合综国产精品 | 深夜免费小视频 | 欧美aaaxxxx做受视频 | 高清有码中文字幕 | 日韩精品国产一区 | 91成人在线观看喷潮 | 成年美女黄网站色大片免费看 | www.天天草 | 999久久久免费视频 午夜国产在线观看 | 国产精品观看视频 | 超级碰视频 | 亚洲涩涩网 | 久久久免费 | 一级成人免费视频 | 精品欧美一区二区在线观看 | 99在线国产 | 久久精品中文字幕少妇 | 欧美日韩精品在线视频 | 久久成人国产精品免费软件 | 免费观看黄 | 国产精品一区二区av | 午夜视频免费 | 97超级碰碰碰碰久久久久 | 亚洲日本成人网 | 91精品影视 | 精品视频在线观看 | 欧美色图东方 | 国产一级片播放 | 欧美韩国日本在线观看 | 国产色久 | 免费色婷婷 | 美女黄频 | 香蕉视频最新网址 | 国产精品99爱 | 视频精品一区二区三区 | 日韩免费中文 | 欧美日韩国产区 | 精品国产亚洲一区二区麻豆 | 日韩另类在线 | 色婷婷丁香 | 亚洲国产日韩欧美 | 国产美女免费观看 | 亚洲1区 在线 | 亚洲精品电影在线 |