分庫分表神器 Sharding-JDBC,幾千萬的資料你不搞一下?
Attempts to establish a connection with the data source that * this {@code DataSource} object represents. * @return a connection to the data source */ Connection getConnection() throws SQLException; /** *
Attempts to establish a connection with the data source that * this {@code DataSource} object represents. * @param username the database user on whose behalf the connection is * being made * @param password the user's password */ Connection getConnection(String username, String password) throws SQLException; } ``` 其中 `CommonDataSource` 是定義資料來源的根介面這很好理解,而 `Wrapper` 介面則是拓展 JDBC 分片功能的關鍵。 由於資料庫廠商的不同,他們可能會各自提供一些超越標準 JDBC API 的擴充套件功能,但這些功能非 JDBC 標準並不能直接使用,而 `Wrapper` 介面的作用就是把一個由第三方供應商提供的、非 JDBC 標準的介面包裝成標準介面,也就是`介面卡模式`。 既然講到了介面卡模式就多囉嗦幾句,也方便後邊的理解。 > 介面卡模式個種比較常用的設計模式,它的作用是將某個類的介面轉換成客戶端期望的另一個介面,使原本因介面不匹配(或者不相容)而無法在一起工作的兩個類能夠在一起工作。比如用耳機聽音樂,我有個圓頭的耳機,可手機插孔卻是扁口的,如果我想要使用耳機聽音樂就必須藉助一個轉接頭才可以,這個轉接頭就起到了適配作用。舉個栗子:假如我們 `Target` 介面中有 `hello()` 和 `word()` 兩個方法。 ``` public interface Target { void hello(); void world(); } ``` 可由於介面版本迭代`Target` 介面的 `word()` 方法可能會被廢棄掉或不被支援,`Adaptee` 類的 `greet()`方法將代替`hello()` 方法。 ``` public class Adaptee { public void greet(){ } public void world(){ } } ``` 但此時舊版本仍然有大量 `word()` 方法被使用中,解決此事最好的辦法就是建立一個介面卡`Adapter`,這樣就適配了 `Target` 類,解決了介面升級帶來的相容性問題。 ``` public class Adapter extends Adaptee implements Target { @Override public void world() { } @Override public void hello() { super.greet(); } @Override public void greet() { } } ``` 而 `Sharding-JDBC` 提供的正是非 JDBC 標準的介面,所以它也提供了類似的實現方案,也使用到了 `Wrapper` 介面做資料分片功能的適配。除了 DataSource 之外,Connection、Statement、ResultSet 等核心物件也都繼承了這個介面。 下面我們通過 `ShardingDataSource` 類原始碼簡單看下實現過程,下圖是繼承關係流程圖。 ![](https://upload-images.jianshu.io/upload_images/15462057-fd6eee5a485dbd9c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) `ShardingDataSource` 類它在原 `DataSource` 基礎上做了功能拓展,初始化時註冊了分片SQL路由包裝器、SQL重寫上下文和結果集處理引擎,還對資料來源型別做了校驗,因為它要同時支援多個不同型別的資料來源。到這好像也沒看出如何適配,那接著向上看 `ShardingDataSource` 的繼承類 `AbstractDataSourceAdapter` 。 ``` @Getter public class ShardingDataSource extends AbstractDataSourceAdapter { private final ShardingRuntimeContext runtimeContext; /** * 註冊路由、SQl重寫上下文、結果集處理引擎 */ static { NewInstanceServiceLoader.register(RouteDecorator.class); NewInstanceServiceLoader.register(SQLRewriteContextDecorator.class); NewInstanceServiceLoader.register(ResultProcessEngine.class); } /** * 初始化時校驗資料來源型別 並根據資料來源 map、分片規則、資料庫型別得到一個分片上下文,用來獲取資料庫連線 */ public ShardingDataSource(final