MyBatis從目前最流行的關系數據庫訪問方法中吸收了大量的優秀特征和思想,並找出其中的協同增效作用。下圖展示了MyBatis框架是如何吸收我們在多年使用不同方式進行數據庫集成的 開發過程中所學到的知識,並將其中最優秀的思想結合起來,形成這個混合型解決方案的。
接下來的幾節將討論這些不同的數據庫訪問方法,以及iBATIS從每種方法中汲取的優秀思想。
SQL
MyBatis的核心是SQL。從根本上說,所有的關系數據庫都支持SQL,並將它作為與數據庫交互的主要方式。SQL是一種簡單的、非過程化的語言,用於操縱數據庫,其實SQL包含兩種語言。
第一種就是數據定義語言(Data Definition Language, DDL),其中包含像CREATE、DROP以 及ALTER這樣的語句。這些語句用於定義數據庫數據及其設計,包括表(table)、列(column)、 索引(index)、約束(constraint)、過程(procedure)以及外鍵關系(foreign key relationship)。iBATIS 並不直接支持DDL。雖然許多人的確通過iBATIS成功地執行了DDL,但我們不推薦這樣做,因為 DDL通常應該由某個數據庫管理小組擁有並控制,應用程序的開發人員無權操縱它。
SQL所包含的第二種語言就是數據操縱語句(Data Manipulation Language,DML)。DML包
括像SELECT、INSERT、UPDATE以及DELETE這樣的用於直接操縱數據的語句。最初,SQL被設計 為一種簡單得足以讓終端用戶(end user)可以使用的語言。按照這種設計思想,圖像用戶界面 就完全不需要了,甚至連應用程序也不需要了。當然,這種情況得回溯到當年那個永遠是“黑屏 上閃着光標”的時代了,在那個時代我們才可以對終端用戶報以更多的期望。
今非昔比,數據庫已經變得太復雜了,不能指望終端用戶通過SQL來直接操縱數據庫了。你 能想象這樣的情況嗎:將一大堆SQL語句交給會計部門,然后對他說,“就這些了,查找一下 BSHEET表你就能找到所需要的信息。”這簡直是不可能的了。
僅僅SQL本身已經再也不可能作為終端用戶的一個有效接口 了,但對於開發人員來說SQL仍 然是一個非常強大的工具。SQL是唯一具有完整的數據庫訪問功能的方法,所有其他的工具都不 過是該完整功能的一個子集。正是這個原因,MyBatis完全支持SQL,並將它作為關系數據庫訪問 的主要方式。同時,MyBatis也具有許多其他方法的優點,這些方法包括存儲過程和對象/關系映 射工具。
1.老式存儲過程
存儲過程(stored procedure)也許可以算是為關系數據庫編寫應用程序的最古老的方式了。 許多遺留系統使用的都是我們現在稱為“兩層(two-tier)”的設計。“兩層設計”包括一個富客戶 端界面來直接調用數據庫中的存儲過程。這些存儲過程中可能包含可用於操縱當前數據庫的 SQL。除了SQL,這些存儲過程還可能含有(通常也的確含有)業務邏輯。與SQL不同,編寫這 些存儲過程時使用的語言是過程化的,具有像條件語句和迭代語句這樣的流程控制語句。事實上, 僅僅使用存儲過程就可以創建一個完整的應用程序。許多軟件開發商也開發了像Oracle Forms、 PowerBuilder和Visual Basic這樣的富客戶端工具來支持“兩層”的數據庫應用程序的開發。
“兩層應用程序”的最大問題在於其性能和擴展性。雖然數據庫的功能的確非常強大,但它 們往往未必是處理成百上千甚至上百萬個用戶訪問的最佳選擇。對於現代Web應用程序來說,對 擴展性的需求並不少見。數據庫在並發訪問量、硬件資源以及網絡套接字等方面的限制,將使得 這種“兩層”架構在需要擴大規模時面臨失敗的危險。此外,“兩層應用程序”的部署也是一場 噩夢。除了通常的富客戶端部署問題外,復雜的運行時數據庫引擎也需要部署到客戶端機器上去。
2.現代存儲過程
在某些圈子中存儲過程仍被認為是三層(three-tier)和八層(N-tier)應用程序(例如Web應 用程序)的最佳實踐。但現在存儲過程通常被當作來自中層(middle tier)的遠程過程調用(remote procedure call, RPC),並且許多性能方面的約束也可以通過建立間接池和數據庫資源管理等方式 解決了。在現代的面向對象的應用程序中,存儲過程仍然是實現完整的數據訪問層的一個行之有 效的設計選擇。存儲過程在性能方面的確具有優勢,因為它們總是能夠比任何其他的解決方案更 快地完成數據庫中的數據操作。但是,還有比性能更需要關注的問題。
將業務邏輯放在存儲過程中通常都被認為是一個糟糕的設計。最主要的原因就在於存儲過程 的開發很難符合現代應用程序的架構。它們難以編寫、難以測試、同時也難以部署。更糟糕的是, 現代企業中數據庫通常由其他的數據庫管理小組擁有,並且受到最為嚴格的變更控制的保護。它 們通常無法快速變更以適應現代軟件開發方法學的需要。此外,要用存儲過程來實現完整的業務 邏輯,其自身也存在某些限制。如果業務邏輯需要訪問其他的系統、資源或用戶界面,存儲過程 很可能就無法處理所有這些邏輯了。現代應用程序非常復雜,需要更加通用的語言,而不是像存 儲過程這樣僅僅優化了數據操縱能力的專用語言。為解決這個問題,有些開發商在它們的數據庫 引擎中嵌入了像Java這樣的更加強大的語言,來編寫更加強壯的存儲過程。但這其實根本沒有解 決問題,它只會使得應用程序與數據庫的邊界變得更加模糊,並為數據庫管理員帶來新的負擔: 他們現在需要開始擔心數據庫中的Java和C#了。對於解決問題,這實在是一個錯誤的工具。
軟件開發中經常出現的一個場景就是矯枉過正(overcorrection)。當發現問題時,嘗試的第一個解決方案往往是完全相反的方法。這非但沒有解決問題,其結果往往是引入等量的完全不同的新問題。例如我們下面要討論的內聯SQL。
系列文章: