有開發者引用物理學隱喻:“粒子的位置與動量不可同時確定”,暗示在框架設計中,通用性與專用性難以兼得。更有人直言,任何嘗試“大一統”的框架,最終都會淪為“四不像”,不僅丟掉了數據庫的強事務優勢,也沒能發揮出例如 Elasticsearch 的能力。
面對這些質疑,dbVisitor 依然堅定地提出了"One API Access Any DataBase"的愿景。為什么我敢這么說?今天我們就來拆解這個爭議,聊聊 dbVisitor 敢于挑戰“大一統”的底氣究竟在哪里。
我們對 API 的誤解
要理解為什么 “大一統” 是可行的,我們首先需要厘清兩個長期以來混淆視聽的誤區。
1. API 業務化
目前的 Java 數據庫訪問領域,出現了一種明顯的趨勢:API 越來越“業務化”。
什么是業務化?
為了解決特定領域的復雜查詢問題,數據庫訪問框架開始追求極致的開發效率。 例如一些優秀項目:SqlToy-ORM 在處理極致的分頁優化、緩存翻譯以及層次化數據查詢(如遞歸查詢)方面表現卓越, 往往能用極簡的配置解決令人頭禿的 SQL 難題;而 Easy-Query 則在類型安全的動態查詢構建上做到了極致,讓你在 Java 代碼中就能以結構化的方式編寫出極其復雜的業務邏輯。
價值:對于特定領域的復雜查詢(如多表關聯、動態聚合、行轉列)它們甚至能通過很少的代碼替代幾十行原生 SQL。這種效率提升是巨大的,值得充分肯定。
局限:這種“神器”級別的 API 往往與數據庫的特性強綁定。例如 MySQL 的復雜查詢邏輯,直接照搬到 MongoDB 或 Elasticsearch 上是完全行不通的。
dbVisitor 的選擇:回歸基座
回顧 Hibernate、MyBatis、DBUtils 甚至 JDBC 本身,這些生命力持久的項目都有一個共性:職責單一、目標明確。它們不做業務邏輯,而是專注做基座。
MyBatis Plus 在國內的巨大成功,正是建立在 MyBatis 這個堅實的 “非業務化” 基座之上。MyBatis 負責映射,MP 負責提供更高級的特性和封裝。
通用性的價值在于做“房屋的骨架”。dbVisitor 的目標并非替代 Easy-Query 這類工具去解決具體業務的復雜查詢,而是立志成為新時代的數據訪問基座。 只有基座穩固且統一,上層的業務生態(就像 MyBatis 生態)才能在不同數據源上百花齊放。
2. “簡單模式無用論” 的謬誤
反對者常由兩個觀點:
“CRUD 太簡單,統一了也沒價值”
“統一 API 無法跨越數據庫特性的鴻溝”
反駁觀點一:簡單 CRUD 的普世價值
如果你的世界里只有 MySQL 和 Oracle,那么非常確實,JDBC 已經統一了,再造輪子沒意義。 但如果你的技術棧加入了MongoDB、Elasticsearch、Redis呢?
MongoDB 插入一條數據用 “db.collection.insertOne()”
Elasticsearch 插入一條數據用 “POST /indexName/_doc ...”
Redis 插入一條數據用 “set xxx”命令
這些“簡單”的操作,API 風格天差地別。在"One API Access Any DataBase"的愿景下,能用統一的insert(entity)完成上述所有操作,本身就具有極高的普世價值,它消除了認知切換的成本。
反駁觀點二:API 不僅僅是查詢構造器
這是一個巨大的思維誤區:“統一 API” 不等于 “統一成某一特定的接口”。
查詢構造器是不是 API?當然是!
Mapper 接口(Dao)是不是 API?當然是!
MyBatis 的 Mapper XML 綁定是不是 API?當然是!
底層的JDBC Connection是不是 API?更是!
人們鄙棄 Mapper + XML,往往是因為它寫起來繁瑣(重復勞動),但在架構層面,Mapper 接口綁定 DSL是最符合“行為中心”的 API 設計。 它將“業務意圖”(方法名)與“具體實現”(SQL/DSL)剝離。
只要我們不再執著于用 Java 代碼去描述一切查詢,而是接受“API 定義行為”這個理念,跨越數據庫特性的鴻溝就可以迎刃而解。
dbVisitor 的核心思想
沒有靈丹妙藥,任何試圖發明一種 “萬能 Java 語法”來生成所有數據庫查詢的嘗試,都注定失敗。
dbVisitor 之所以敢說“可以”,是因為其核心思想并非去消滅差異尋求發明萬能語法, 而是通過JDBC 標準化和分層抽象來管理差異。并通過獨特的雙層適配器架構來彌合鴻溝:
JDBC 標準化
這層是 dbVisitor 達成 “One API Access Any DataBase” 愿景的根基。
復用 JDBC 標準
沒有發明新協議,而是為 NoSQL(MongoDB, Elasticsearch, Redis)編寫了遵循 JDBC 規范的驅動。 并使用這些數據庫官方原始的 DSL 語言來進行數據庫操作。這些驅動在內部也僅僅是將 JDBC 的操作映射到各自的原生 SDK 調用上,并將返回值映射成 JDBC 標準方式。
Request/Response 模型
為了簡化異構數據源的接入,復雜的 JDBC 狀態管理被簡化為輕量級的 Request/Response 模型。這使得你可以用很少的代碼即可接入一個全新的非標準的數據源。 新的數據源,甚至直接被HikariCP管理。在使用它們的時候,除了查詢語法不是 SQL 意外其它完全一致。
正是基于上述特征 dbVisitor 在進行適配 Elasticsearch 時只使用了約 20 個類,總共 2300 行代碼,極其輕量。
One API
這里的“One API”并非指用一個死板的接口去涵蓋一切,而是指構建 一種統一的數據交互標準, dbVisitor 的設計哲學認為,真正的統一不是強行把所有數據庫操作都塞進同一個狹窄的入口,而是通過分層抽象在不同的維度上提供統一的體驗。
![]()
dbVisitor 為不同的場景設計了不同級別的抽象接口,以應對不同的行為需求:
LambdaQuery(屏蔽差異) Mapper / XML(管理差異) JDBC Template(透傳執行) 統一 API ≠ 統一能力
盡管 dbVisitor 統一了 insert/update/commit 等調用形式,但它不能改變底層數據庫的物理特性。 對于 MongoDB、Elasticsearch 等弱事務或無事務的存儲,調用commit()可能只是邏輯上的空操作,并不意味著具備了關系型數據庫的 ACID 強一致性保障。
實戰:多維度的統一體驗
讓我們通過代碼,看看這套理念是如何落地的。
1. 簡單維度(類型安全)
無論底層是 MySQL 還是 Elasticsearch,標準的 CRUD 代碼完全一致。
![]()
2. 業務維度(行為為中心)
當我們需要發揮 ES 的聚合能力或 MySQL 的復雜 Join 時,Mapper 接口是最佳選擇。dbVisitor 提供了三種使用 Mapper 的姿勢,你可以根據業務復雜度靈活混用。
方式一:純 Java 構建
這是 dbVisitor 一種方式,通過繼承 BaseMapper并利用 Java 8 的default 方法,你可以在 Mapper 接口內部直接使用查詢構造器完成 DAL 邏輯。 這種方式既避免了 XML 的繁瑣,又不像注解那樣將 SQL 硬編碼在 Java 文件中,完美實現了“零 SQL”開發。
![]()
方式二:基于注解
對于中等復雜度的查詢,直接在接口方法上使用注解是最簡潔的方式。你無需編寫額外的 XML 文件,即可完成 SQL 或 DSL 的綁定。
![]()
方式三:基于 Mapper 文件
當 SQL 變得極度復雜(如幾百行的報表 SQL),或者公司有嚴格的 DBA 審查流程(需分離 SQL 文件)時,XML 依然是不可替代的方案。
Java 接口(定義行為):
![]()
XML 實現(定義邏輯):這里展示了 dbVisitor 的強大之處:在 XML 中寫不同數據庫的方言。
![]()
3. 靈活維度:(原生體驗)
這是 dbVisitor 的“逃生艙”。當上層所有的抽象都無法滿足你的特殊需求時,比如需要極致的性能優化、使用數據庫特有的非標指令,或者集成QueryDSL等第三方框架,你可以退回到這層。
場景一:原生 SQL/Shell 透傳
直接下發數據庫能識別的原生命令,無需任何轉譯。
![]()
場景二:底層 API 可達
你可以隨時打破封裝,直接操作底層的Connection。對于 NoSQL 數據源,dbVisitor 的驅動層也遵循了 JDBC 的Wrapper規范,允許你 unwrap 出官方的原生驅動對象。
![]()
為何選擇 dbVisitor?
很多人會問:“這不就是把 MyBatis 和 Spring 縫合了一下嗎?” 其實并非如此。dbVisitor 不是簡單的“膠水”,而是基于統一架構的重新設計。
![]()
1. 獨立的雙層適配能力
dbVisitor 是One API + Driver。 即便你不打算替換現在的 MyBatis,你依然可以單獨使用 dbVisitor 的JDBC Driver。把它放入你的 Spring Boot + MyBatis 項目中,你的 MyBatis 立刻就具備了操作 MongoDB 和 Elasticsearch 的能力! 這是一種“降維打擊”般的兼容性。
2. 底層架構的高度統一
如果你嘗試過在項目中混用 MyBatis 和 Spring JDBC,你會發現割裂感很強:
MyBatis 的TypeHandler在 Spring JDBC 里用不了。
Spring 的RowMapper在 MyBatis 里無法復用。
事務管理器配合往往有坑。
JDBC Template、LambdaQuery、Mapper XML 全部共享同一套TypeHandler 機制、同一套Session 管理、同一套元數據映射。 在 dbVisitor 中,你可以在 Lambda 查詢中復用 Mapper 定義的 ResultMap,這種底層的一致性是簡單的拼湊無法比擬的。
3. 生態框架的無關性
這是 dbVisitor 區別于 Spring Data 或 MyBatis-Plus 的另一個重要特征。 dbVisitor 的核心不依賴 Spring,也不依賴任何 Web 容器。它基于純 Java (JDK 8+) 和 JDBC 標準構建。 這意味著:
你可以在Spring Boot中用它。
你可以在Solon、Vert.x、Quarkus中用它。
你甚至可以在一個沒有任何依賴的 Main 方法控制臺程序中直接 new 出來使用它。
這種零耦合的特性,讓它不僅能適應現有的各種技術棧,更能在未來的架構演進中保持生命力,不會被綁定在某個特定框架的戰車上。
結語
物理學告訴我們要敬畏差異,但軟件工程告訴我們要通過抽象來管理復雜。
dbVisitor 并不試圖用“大一統”去掩蓋數據庫的特性,而是通過提供一個統一的基座(JDBC Driver)和分層的 API 設計,讓開發者在簡單場景享受“大一統”的便利,在復雜場景擁有“原生級”的掌控。這就是 dbVisitor 敢于挑戰數據訪問“大一統”的底氣。
- 項目首頁:https://www.dbvisitor.net/
- 項目源碼:https://gitee.com/zycgit/dbvisitor
如果你對這個項目非常感興趣不妨 “加個關注” 及對我支持一下。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.