當 Java 1.0 于 1996 年推出時,語言和互聯網都與今天大不相同。當時,網絡主要是靜態的,而 Java 承諾通過注入交互式游戲和動畫來為網絡注入活力,這一承諾極具前景。根據 1995 年寫給《連線》雜志的 David Banks 的說法,Java 是自 Netscape 以來最熱門的技術。
為了更好地理解,Java 的起源可以追溯到 1990 年,當時 Sun Microsystems 在消費市場中的定位舉步維艱。在那個時期,他們開發了 Oak,一種旨在實現平臺無關、輕量級且非常適合網絡環境的編程語言。他們的首次嘗試是將 Oak 商業化,用于交互式電視。
到 1994 年,互聯網開始普及,Sun 公司認識到 Oak 是其完美的應用程序。與傳統軟件不同,Oak 允許小程序(小型可移植程序)在任何帶有解釋器的機器上運行,使其非常適合網絡應用程序。Oak 被重新命名為 Java,其解釋器被命名為 Java 虛擬機,并創建了一個原型瀏覽器 HotJava 來展示其功能。
然而,Java 1.0 缺乏標準化的數據庫連接。當時互聯網仍處于起步階段,數據庫主要應用于企業級應用而非基于網絡的軟件。因此,Java 的初始設計重點在于創建能夠在不同平臺上無縫運行的應用程序,而非與后端數據存儲系統集成。考慮到當時的背景——數據庫領域由 Oracle 7、IBM DB2、Sybase SQL Server 和 Informix 等重型關系型數據庫系統主導。這些系統是為傳統客戶端-服務器架構和企業工作負載設計的,具備復雜的交易處理能力和查詢優化器。雖然存在 ObjectStore 和 GemStone 等面向對象數據庫,但它們仍屬于小眾產品,主要用于專門的工程和電信應用。"網絡規模"數據庫的概念還有數年時間才會出現。
Java 的跨平臺性和架構中立設計使其對程序員和企業都具有吸引力。1997 年,在 IBM 工作的 Eli Javier 寫信給多倫多的用戶組雜志,表示程序員喜愛 Java 是因為它是第一個真正的網絡編程語言,而企業喜愛它是因為它可以通過簡化應用程序的實施和分發來幫助他們降低成本,因為它可以在任何地方運行,并且可以從中央服務器部署。
就連 IBM 也在 1996 年 Java 1.0 發布后不久,認識到 Java 是網絡計算的基礎。這一轉變在 1997 年得到公開強化,當時 IBM AS/400 部門的總經理比爾·齊特勒明確表示,Java 是 AS/400 業務在網絡計算中的關鍵使能者。
1996年JDBC(Java DataBase Connectivity)誕生
盡管 Java 被迅速采用,但它需要一個統一的方式來與數據庫交互。如果沒有標準,開發者必須編寫特定數據庫的代碼,這威脅到了 Java 的可移植性。為此,Sun Microsystems 在 Java 1.0 發布后的三個月內推出了 Java 數據庫連接 API(JDBC)。受 Microsoft 的 ODBC 啟發,JDBC 允許應用程序使用單一接口與數據庫交互。到 1996 年年中,JDBC 1.0 最終確定,標志著向企業計算邁出了重要一步。
借助 JDBC,Java 不再僅僅是 applet 和交互式 Web 應用程序的語言,它現在成為企業軟件開發的一個可行選項。到 20 世紀 90 年代末,像 Oracle、IBM、Sybase、SAS 和 Borland 等主要數據庫廠商已經全面擁抱 Java,并為他們的數據庫提供了官方的 JDBC 驅動程序。
雖然 JDBC 是一個突破,但它并非完美解決方案——隨著 Java 應用程序的復雜性增加,開發者開始遇到限制。開發者不得不編寫大量重復代碼來執行簡單查詢。每次數據庫操作都需要手動管理連接、語句和結果集。同時,異常處理既冗長又繁瑣,需要使用 try-catch-finally 塊進行正確的清理。
對象-關系映射不匹配的弊端開始顯現。數據庫表和對象是兩種截然不同的數據存儲介質。關系型數據庫通過關系和約束來關注數據的規范化和完整性,而面向對象編程則強調封裝、繼承和多態。這種根本性的脫節意味著開發者必須不斷在這兩種范式之間進行轉換。具有豐富層次結構和復雜關系的對象必須被扁平化為表格,而規范化的數據庫模式則必須被重新組裝成相互連接的對象圖。在一個世界中的簡單概念在另一個世界中變得復雜——Java 中的一個基本繼承層次結構可能需要在數據庫中通過多個連接表來實現,而一個簡單的數據庫視圖可能需要多個相互關聯的類來在對象世界中正確表示。這種阻抗不匹配不僅使開發更加復雜,還影響了性能,因為每次范式之間的轉換都會給數據庫操作增加額外開銷。
1998年EJB(Enterprise JavaBeans)誕生
為了應對這些挑戰,J2EE(Java 2 企業版)在 1998 年引入了企業 JavaBeans(EJB)。正如 Cliff Berg 在 1999 年給 Info World 寫信中所說,EJB 的主要目標是簡化企業應用開發,讓軟件開發者能夠專注于業務邏輯,而不是構建自定義的基礎設施。EJB 通過內置的事務管理、安全和可擴展性簡化了企業開發。
該模型區分了不同類型的 Bean:會話 Bean,用于管理業務邏輯和用戶交互;實體 Bean,用于表示持久化數據。EJB 的一個主要創新是容器管理持久化(CMP),它允許數據庫交互由應用服務器自動處理,而無需開發者編寫顯式的 SQL 查詢。
通過 CMP,開發者可以定義表示數據庫記錄的實體 Bean,而 EJB 容器會自動處理這些對象的持久化、更新和檢索。這不僅減少了樣板代碼的量,還提高了數據庫可移植性,因為應用程序不再需要與特定的 SQL 語法或數據庫供應商緊密耦合。
EJB 還引入了聲明式事務管理,這是對傳統數據庫事務處理的重要改進。它不再需要開發者手動管理事務(如在代碼中調用 commit() 和 rollback()),而是允許通過部署描述符以聲明方式配置事務。
EJB 旨在解決的另一個數據庫相關挑戰是連接池。建立數據庫連接是一項耗時的操作,為每個請求打開新的連接會導致嚴重的性能瓶頸。
但盡管 EJB 的數據庫管理方法取得了進步,但它也存在問題。實體 Bean 模型常因其性能低效而受到批評,特別是在處理大規模持久化方面。CMP 雖然方便,但引入了顯著的開銷,因為容器必須動態生成 SQL 并在后臺管理數據庫操作。有時開發者發現,為了性能調優,需要使用 Bean 管理持久化(BMP),即顯式編碼數據庫操作。
2001年Hibernate誕生
因 EJB 的復雜性而感到沮喪,Gavin King 于 2001 年開發了 Hibernate,這是一個對象關系映射(ORM)框架。他對 Hibernate 的目標是創建一個開源的對象關系映射(ORM)框架,提供透明的持久化,允許開發者使用普通的 Java 對象(POJOs),而不是管理手動 SQL 查詢和數據庫事務。
與 JDBC 不同,在 JDBC 中,數據庫查詢作為字符串嵌入在代碼中,Hibernate 引入了一種聲明式映射系統,允許開發人員在 XML 配置文件中定義數據庫關系。這種方法將數據庫邏輯與應用程序代碼分離,使得在不破壞應用程序邏輯的情況下更容易修改模式。
Hibernate 最顯著的貢獻之一,正如 Mario Aquino 在 2003 年所寫的那樣,是通過映射配置實現了一對一、一對多和多對一的關系,從而消除了開發人員手動處理代碼中的連接和外鍵的需要。此外,Hibernate 支持懶加載、級聯刪除和外連接抓取,允許應用程序通過減少與數據庫的往返次數來優化數據庫交互。
Hibernate 的另一個主要優勢是代碼生成和自動化。Hibernate 可以根據對象關系映射定義生成 Java 源文件。這消除了傳統 JDBC 應用中所需的大部分手動編碼。與 Hibernate 集成的工具(如 Middlegen)甚至可以分析數據庫模式并自動生成 Hibernate 映射文件。相比之下,EJB 實體 Bean 需要手動部署描述符和冗長的 XML 配置,這使得它們難以維護和部署。
為了進一步簡化應用架構,Hibernate 還引入了一種輕量級且靈活的事務模型。它提供了內置的事務管理,允許開發人員在不直接管理 JDBC 事務的情況下持久化、更新和刪除對象。這與 EJB 的容器管理事務形成了鮮明對比,后者迫使開發人員必須在 Java EE 服務器的約束下工作。通過 Hibernate,事務可以通過編程方式或聲明式進行處理,提供了更多的控制和靈活性。
到 2003 年,Hibernate 已經成為數據持久化的首選替代方案,取代了 EJB 實體 Bean。它的成功影響了 Java 的官方 ORM 標準。
2006年JPA(Java Persistence API)規范制定
2006 年,鑒于 Hibernate 等 ORM 框架的成功,Java 社區進程(JCP)成立了 JSR 220,該規范將 Java 持久化 API 作為 EJB 3.0 的一部分引入,而 EJB 3.0 又是 Java EE 5 的一部分。
JPA 標準化了 ORM 的不同實現,如 Hibernate、TopLink 和 JDO。它用注解取代了冗長的 XML 配置,引入了 Java 持久化查詢語言(JPQL),并允許開發者使用輕量級的 POJO 代替重量級的實體 Bean。JPA 迅速使 EJB 實體 Bean 過時。
注解取代了 XML 配置的需求,使得持久化映射更加清晰。EJB 2.1 需要冗長的 XML 描述符來定義實體映射,但通過 JPA,像@Entity、@Id 和@OneToMany 這樣的簡單注解使得定義持久化規則變得容易得多。此外,JPA 引入了 Java 持久化查詢語言(JPQL),這是一種面向對象的查詢語言,改進了傳統 SQL 和有限的 EJB QL。
與需要 Java EE 容器的 EJB 實體 Bean 不同,JPA 可以在獨立的 Java SE 應用程序中使用。這種靈活性使開發人員能夠在企業應用程序和小型 Java 項目中使用 JPA,而無需應用程序服務器的額外開銷。此外,JPA 提供了自動事務管理,使開發人員無需手動處理提交和回滾操作。
JPA 的另一個關鍵優勢是其供應商獨立性。API 定義了一個標準的持久化模型,但開發人員可以選擇任何 JPA 提供者,例如 Hibernate、EclipseLink 或 OpenJPA。這種解耦提供了更多的靈活性,并減少了依賴特定的 ORM 實現。
盡管 Hibernate 已經得到廣泛使用,JPA 的標準化為企業應用帶來了統一性。許多項目繼續將 Hibernate 作為 JPA 提供者使用,但現在他們可以依賴一個通用的 API,而不是被鎖定在單一的 ORM 框架中。Hibernate 的許多創新最終都融入了 JPA 標準:通過代理對象實現的透明懶加載、處理實體生命周期狀態(臨時、持久和分離)的解決方案、用于跟蹤實體變化的持久化上下文概念,以及其復雜的緩存機制。
就連 JPA 的查詢語言(JPQL)也深受 Hibernate 的 HQL(Hibernate 查詢語言)影響,采用了面向對象的查詢方法。其他塑造了 JPA 的關鍵 Hibernate 特性還包括其用于管理實體關系的級聯操作、用于并發控制的樂觀鎖策略,以及其請求會話模式,這一模式最終演變成了 JPA 的 EntityManager 概念。
隨著 JPA 在 2006 年的引入,EJB 實體 Bean 迅速過時。開發者現在可以訪問一個更簡單、更直觀的持久化模型,而無需 EJB 的重重量特性。JPA 也加速了 Java EE 5 的采用,使企業開發更加便捷。
JPA 簡化了數據庫訪問,但管理倉庫和編寫查詢仍然繁瑣。開發者仍然需要為倉庫管理編寫樣板代碼。獲取、更新和刪除記錄需要定義自定義查詢或編寫大量代碼。
除此之外,到了 21 世紀頭十年末,NoSQL 數據庫的興起正在重塑數據存儲格局。雖然關系型數據庫在幾十年間一直是主流選擇,但網絡應用、大數據和實時處理的爆炸式增長帶來了傳統關系型數據庫難以滿足的新需求。MongoDB、Cassandra、Redis 和 Neo4j 等 NoSQL 數據庫因其為特定場景提供了更好的可擴展性、靈活性和性能而廣受歡迎。與強制執行嚴格模式的關系型數據庫不同,NoSQL 數據庫允許更動態的數據模型,使其成為云原生應用和分布式系統的理想選擇。
2010年Spring Data誕生
認識到需要一種更簡單、更統一的方式來與關系型和非關系型數據庫交互,Spring Data 于 2010 年作為 Spring 生態系統的一部分被引入。其目標是為數據訪問提供一致的、高級的抽象,消除重復的樣板代碼,并讓開發者能夠專注于業務邏輯而不是基礎設施。Spring Data 不再需要手動定義查詢或實現倉庫模式,而是引入了倉庫的概念,這些倉庫根據方法名自動生成查詢,減少了開發者需要編寫的代碼量。
在 Spring Data 旗下發布的第一個模塊是 2011 年 4 月發布的 Spring Data Neo4j,僅僅幾個月后,在 2011 年 7 月,Spring Data JPA 1.0 發布了。
雖然 JPA 已經簡化了 ORM,但 Spring Data JPA 更進一步,引入了自動查詢生成、分頁和聲明式事務管理。開發者不再需要為簡單查詢編寫 SQL 或 JPQL——Spring Data JPA 可以從方法名中推導出查詢,使數據庫訪問更加直觀,并減少了樣板代碼的需求。
2011年Spring Data MongoDB誕生
2011 年 10 月,Spring Data MongoDB 1.0 發布。此時,MongoDB 已成為主流的 NoSQL 文檔數據庫,為開發者提供了靈活的無模式數據模型。與需要復雜遷移才能更改模式的傳統關系型數據庫不同,MongoDB 允許應用程序動態演進。
2012年Spring Data Redis 誕生
下一個重要里程碑出現在 2012 年 5 月,Spring Data Redis 1.0 發布。與傳統數據庫不同,Redis 是一個以內存優先的鍵值數據庫,以其卓越的速度和多功能性而聞名。最初于 2009 年開發,Redis 迅速成為現代架構的關鍵組成部分,支持緩存層、實時分析、會話存儲,甚至消息代理系統。
未來展望
在接下來的幾年里,新的 Spring Data 集成不斷發布,而隨著多模型數據庫、無服務器數據庫和邊緣計算的出現,該領域繼續快速發展。這讓我們不禁思考:當面對不斷變化的數據世界時,Java 將何去何從?
未來并非在于選擇 SQL 還是 NoSQL,而在于為合適的任務選擇合適的數據模型。這一理念體現在像 CockroachDB 和 FaunaDB 這類現代數據庫中,它們模糊了傳統分類的界限,同時提供 SQL 接口和分布式 NoSQL 般的可擴展性。
Java 數據訪問庫的演進似乎也遵循這一趨勢。Project Loom 的虛擬線程承諾將革新 Java 處理數據庫連接的方式,可能使反應式編程模式在高吞吐量應用中從必要條件變為可選條件。我們可以預期 Java 平臺上的數據訪問將演進為在不同數據模型之間提供一致體驗,同時利用 Java 的新并發特性。
人工智能和機器學習的興起也在推動 Java 進行適應。數據領域的新寵是向量數據庫。盡管向量數據庫已經存在一段時間,但新獲得的能力——即尋找 AI 模型為任何非結構化數據創建向量表示——提升了數據庫有效處理向量和向量操作(如通過 KNN/ANN 進行語義搜索)的需求。
我們正看到 Java 應用程序對無縫交互向量數據庫和大型語言模型的需求日益增長,同時保持 Java 開發人員所期望的類型安全性和可靠性。我們將看到針對這些用例的新標準出現嗎?就像 JPA 標準化 ORM 一樣。Java 將如何演變以應對邊緣實時數據處理需求的增長?隨著無服務器數據庫的普及,Java 的傳統連接池和事務管理模式將如何適應這些新范式?這一趨勢已經在 Spring AI 等項目中有可見跡象。