ShardingSphere-JDBC:數(shù)據(jù)分片源碼篇
前言
在上篇我們已經(jīng)通過一個簡單的demo(ShardingSphere-JDBC:數(shù)據(jù)分片實戰(zhàn)篇)實現(xiàn)了數(shù)據(jù)分片,在本文我們會通過深入源碼分析"ShardingSphere-JDBC"是如何實現(xiàn)改寫sql語句的?
也就是說,我們只是寫了“SELECT * FROM t_order WHERE order_id = ? AND user_id = ?”,他是如何做到數(shù)據(jù)改寫,路由到“ds1庫t_order1表”的。
下面我們會按照上篇實戰(zhàn)的demo逐行去分析。
獲取數(shù)據(jù)源

UML時序圖

在這里主要就是初始化運行時上下文環(huán)境,包括:
初始化數(shù)據(jù)源。
初始化策略。
初始化執(zhí)行引擎。
初始化SQL解析器引擎。
初始化事務(wù)管理器。
建立連接

UML時序圖

在這里的操作主要包括:
獲取數(shù)據(jù)源。
獲取運行時上下文環(huán)境。
獲取事務(wù)管理器。

獲取預(yù)編譯 SQL 語句

UML時序圖

在這里的操作主要包括:
獲取數(shù)據(jù)庫連接。
獲取sql語句。
獲取ParameterMetaData。
獲取PreparedQueryPrepareEngine。
獲取PreparedStatementExecutor。
獲取BatchPreparedStatementExecutor。

執(zhí)行sql語句

UML時序圖

在這里的操作主要包括:
清除預(yù)編譯執(zhí)行器的緩存。
獲取執(zhí)行上下文。
初始預(yù)編譯執(zhí)行器的緩存。
合并執(zhí)行查詢。
獲取結(jié)果集。
釋放資源。

在這里我們重點關(guān)注的是第2點也就是執(zhí)行prepare()方法,它在這個方法中是如何改寫sql語句的?

首先它會調(diào)BasePreparedEngine.prepare()方法,在這里調(diào)用executeRoute()方法生成RouteContext(),最終在DataNodeRouter.route()方法中生成RouteContext對象。
注意,在這個對象里有一個屬性很重要,就是“routeResult”。在routeResult中有兩個屬性,分別是originalDataNodes和routeUnits,接下來我們會用到。

生成ExecutionContext,這個是返回值,我們先不管,重點是看一下executeRewrite()方法,從字面意思是就是重寫執(zhí)行語句。

在該方法中,我們只看最后一行也就是rewrite()方法,這個方法只有5行代碼,我們看一下只是給結(jié)果循環(huán)賦值。

我們在看new SQLRouteRewriteEngine().rewrite(),在這里它會獲取routeResult的routeUnits屬性,進(jìn)行循環(huán)遍歷,在循環(huán)遍歷中有一個很重要的方法“new RouteSQLBuilder(sqlRewriteContext, each)).toSQL()”,toSQL()方法,看方法名的意思是重寫sql語句。

我們看一下該方法的源碼,這里代碼很簡單,就是根據(jù)條件拼接執(zhí)行的sql語句,看來我們離真相越來越近了,在這里我們要注意一下“getSQLTokenText()”這個方法,我們點進(jìn)去看看。

在這里我們調(diào)用TableToken.toString()方法,在這里有一個很重要的變量“actualTableName”。這個就是我們表改寫。

至此,我們通過對源碼的分析終于明白了他是如何實現(xiàn)數(shù)據(jù)表和數(shù)據(jù)庫的改寫了。
他本質(zhì)就是根據(jù)我們設(shè)置的分庫分表策略對我們寫的sql進(jìn)行重寫和對數(shù)據(jù)庫的篩選。
寫在最后
好兄弟可以點贊并關(guān)注我的公眾號“javaAnswer”,全部都是干貨。
