码农翻身——JDBC的诞生
隨著 Oracle, Sybase, SQL Server ,DB2, ?Mysql 等人陸陸續續住進數據庫村, 這里呈現出一片興旺發達的景象, 無數的程序在村里忙忙碌碌, 讀寫數據庫, ? 實際上一個村落已經容不下這么多人了, 數據庫村變成了數據鎮。
?
這一天, 數據庫鎮發生了一件大事: 它連上了網絡!
?
外部的花花世界一下全部打開, ?很多程序開始離開這個擁擠的城鎮, 住到更加宜居的地方去。
?
可是他們的工作還是要讀寫數據庫, 大家都在想辦法能不能通過網絡來訪問數據庫鎮的數據庫。
?
其中移居到Tomcat村的Java 最為活躍, 這小子先去拜訪了一下Mysql , ? ?相對于Oracle, Sybase 等大佬, Mysql 還很弱小, 也許容易搞定。
?
Java 說: “Mysql 先生, 現在已經網絡時代了, 您也得與時俱進啊, 給我們開放下網絡接口吧。 ”
?
Mysql ?說: “還網絡時代, 你們這些家伙越來越懶了, 都不愿意到我們家里來了! 說說吧, 你想怎么開放? ?”
?
Java 說: “很簡單, 您聽說過TCP/IP還有Socket 沒有? ? 沒有嗎?! ?沒關系, 您的操作系統肯定知道, 它內置實現了TCP/IP和socket, ? 您只需要和他商量一下, 需要申請一個ip , 確定一個端口, 然后您在這個端口監聽, ?我每次想訪問數據了, 就會創建一個socket ,向你發起連接請求, 你接受了就行了。 ”
“這么麻煩啊?”
?
“其實也簡單, 您的操作系統會幫忙的, 他非常熟悉, ?再說只需要做一次就行, 把這個網絡訪問建立起來, 到時候很多程序都會來訪問您, 您會發財的。 ”
?
“不會這么簡單吧, 假設說, 我是說假設啊, ?通過socket我們建立了連接, 通過這個連接, 你給我發送什么東西? ?我又給你發什么東西?” ?Mysql非常老練, 直擊命門。
?
“呃, 這個.... ?”
?
Java 其實心里其實非常明白, 這需要和Mysql定義一個應用層的協議, 就是所謂的你發什么請求, 我給你什么響應。 ?
?
例如:
客戶端程序先給Mysql 打個招呼, ?Mysql也回應一下, 俗稱握手。
?
怎么做認證、授權, 數據加密, 數據包分組。
?
用什么格式發送查詢語句, ? 用什么格式來發送結果。
?
如果結果集很大, 要一下子全發過來嗎?
?
怎么做數據緩沖?
......
等等一系列讓人頭痛的問題。
?
本來Java是想獨自定義, 這樣自己也許能占點便宜, 沒想到Mysql ?直接提出來了。
?
“這樣吧 ” Java 說 “我們先把這個應用層的協議定義下來, 然后您去找操作系統來搞定socket如何? ”
?
“這還差不多 ” 。 Mysql 同意了。
?
兩人忙活了一星期, 才把這個應用層協議給定義好。
?
然后又忙了一星期, 才把Mysql 這里的socket搞定。
?
Java 趕緊回到Tomcat村, ?做了一個實驗: ?通過socket和mysql 建立連接, ?然后通過socket 發送約定好的應用層協議, ? ?還真不錯, 一次都調通了, ? 看來準備工作很重要啊。
?
(劉欣注: 這是我的杜撰, mysql 的網絡訪問早就有了, 并不是java 捷足先登搞出來的)
搞定了Mysql , ?Java 很得意, 這是一個很好的起點, 以后和Oracle, SQL Server, Db2等大佬談判也有底氣了。
?
尤其是和mysql 商量出的應用層協議, ? mysql 也大度的公開了, 這樣一來, 不管是什么語言寫的程序,管你是java, pyhton, ruby , php...... ? 只要能使用socket, ? 就可以遵照mysql 的應用層協議進行訪問, ?mysql 的顧客呈指數級增長, 財源滾滾。 ?尤其是一個叫PHP的家伙, 簡直和mysql 成了死黨。
?
Oracle, Db2那幫大佬一看, 立刻就紅了眼, 不到Java 去談判, 也迫不及待的定義了一套屬于自己的應用層訪問協議。
?
令人抓狂的是, 他們的網絡訪問協議和Msyql 的完全不一樣 ! ?這就意味著之前寫的針對mysql 的程序無法針對Oracle , Db2通用, ?如果想切換數據庫, 每個程序都得另起爐灶寫一套代碼!
?
更讓人惡心的是, 每套代碼都得處理非常多的協議細節, ? 每個使用Java進行數據庫訪問的程序都在喋喋不休的抱怨: 我就想通過網絡給數據庫發送SQL語句, 怎么搞的這么麻煩?
?
原因很簡單, 就是直接使用socket編程, 太low 了 , ?必須得有一個抽象層屏蔽這些細節!
?
Java 開始苦苦思索, 做出一個好的抽象不是那么容易的。
?
首先得有一個叫連接(Connection)的東西, 用來代表和數據庫的連接。 ?
?
想執行SQL怎么辦? 用一個Statement來 表示吧。 ? SQL返回的結果也得有個抽象的概念: ResultSet 。
他們之間的關系如圖所示:
從Connection 可以創建Statement, ? ?Statement 執行查詢可以得到ResultSet。
?
ResultSet提供了對數據進行遍歷的方法, 就是rs.next() , rs.getXXXX .... ? ? ?完美!
?
對了, 無論是Connection, 還是Statement, ResultSet , ?他們都應該是接口,而不能是具體實現。
?
具體的實現需要由各個數據庫或者第三方來提供, 毫無疑問, 具體的實現代碼中就需要處理那些煩人的細節了!
?
Java 把這個東西叫做JDBC, ?想著自己定義了一個標準接口, 把包袱都甩給你別人, 他非常得意。
第一個使用JDBC, 叫做學生信息管理的程序很快發現了問題, ? 跑來質問Java: “你這個Connection 接口設計的有問題!”
?
Java 說: “不可能, 我的設計多完善啊!”
?
“看來你這個規范的制定者沒有真正使用啊, ?你看看, 我想連接Mysql, 把Mysql 提供的jdbc實現(mysql-connector-java-4.1.jar?)拿了過來, ? 建立一個Connection : ”
“這不是挺正常的嗎? 你要連接Mysql , 肯定要提供ip地址, 端口號,數據庫名啊” Java 問到。
?
“問題不在這里, 昨天我遇到mysql了, 他給了我一個號稱性能更強勁的升級版mysql-connector-java-5.0.jar, ?我升級以后, 發現我的代碼編譯都通不過了, ?原來mysql 把MysqlConnectionImpl 這個類名改成了 MysqlConnectionJDBC4Impl ?, 你看看, 你整天吹噓著要面向接口編程, 不要面向實現編程, 但是你自己設計的東西都做不到啊”
?
Java覺得背上開始出汗, ?那個程序說的沒錯, ?設計上出了漏洞, 趕緊彌補吧。
?
既然不能直接去 new 一個Connection 的實現, 肯定要通過一個新的抽象層來做, 這個中間層叫做什么?
?
Java 想到了電腦上的驅動程序, 很多硬件沒法直接使用, 除非安裝了驅動。 ? 那我也模擬一下再做一個抽象層吧:?Driver。
?
每個數據庫都需要實現Driver 接口, ? 通過Driver 可以獲得數據庫連接Connection , ?但是這個Driver 怎么才能new 出來呢? ?肯定不能直接new , ? ?Java似乎陷入了雞生蛋、蛋生雞的無限循環中了。
?
最后, 還是Java的反射機制救了他, 不要直接new 了, ?每個數據庫的Driver 都用一個文本字符串來表示, 運行時動態的去裝載, 例如mysql 的Driver 是這樣的:
Oracle是這樣的:
只要這個Driver Class不改動, 其他具體的實現像Connection, ?Statement, ResultSet想怎么改就怎么改。
?
接下來的問題是同一個程序可能訪問不同的數據庫, 可能有多個不同Driver 都被動態裝載進來, 如何來管理?
?
那就搞一個DriverManager吧, ?Mysql 的Driver, Oracle的Driver 在類初始化的時候, 一定得注冊到DriverManager中來, 這樣DriverManager才能管理啊:
注意: 關鍵點是static 的代碼塊, 在一個類被裝載后就會執行。
?
DriverManager 可以提供一個getConnection的方法, 用于建立數據庫Connection 。
DriverManager會把這些信息傳遞給每個Driver , 讓每個Driver去創建Connection 。
?
慢著! ?如果DriverManager ?里既有MysqlDriver, 又有OracleDriver , ?這里到底該連接哪一個數據庫呢? ? 難道讓兩個Driver 都嘗試一下? 那樣太費勁了吧, 還得區分開,沒法子只好讓那些程序在數據庫連接url中來指定吧:
url中指明了這是一個什么數據庫, 每個Driver 都需要判斷下是不是屬于自己支持的類型, 是的話就開始連接, 不是的話直接放棄。
?
(劉欣注: 每個Driver接口的實現類都需要實現一個acceptsURL(Sting url)方法, 判斷這個url是不是自己能支持的。 )
?
唉,真是不容易啊, Java想, 這下整個體系就完備了吧, 為了獲得一個Connection , 綜合起來其實就這么幾行代碼:
無論是任何數據庫, 只要正確實現了Driver, Connection 等接口, 就可以輕松的納入到JDBC框架下了。
?
Java終于可以高興的宣布: “JDBC正式誕生了!”
?
轉自碼農翻身微信公眾號文章
JDBC的誕生
?
總結
以上是生活随笔為你收集整理的码农翻身——JDBC的诞生的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 码农翻身(随笔)
- 下一篇: 获取Bing主页的背景图片