一. 引言 Spring是一個輕量級的應用程序框架。在許多情況中,Spring都能夠良好地代換傳統的由Java EE應用程序服務器所提供的服務。Spring既是綜合性的也是模塊化的。基於其分層架構,它能夠使開發者靈活地單獨使用其任何一部分。Spring由許多模塊組成,例如IoC容器,AOP,MVC,持久性,DAO和remoting。這些模塊都是相當松耦合的:其中,一些模塊的使用根本不需要另一些模塊。以前,簡直還沒有象Spring應用程序這樣的:你可以選擇使用一些,大多數,或所有的Spring框架支持的組件來構建你的應用程序。
Spring框架所提供的JDBC支持與其它Spring部分並非是緊耦合的,這極有利於代碼的可維護性。本文將向你展示任何直接使用JDBC(也即是,不通過一些O/R映射框架本身使用JDBC)的應用程序是如何從Spring中受益的。
二. 傳統型JDBC 傳統型JDBC有許多積極的方面使之在許多J2SE和J2EE應用程序開發中占有重要地位。然而,也有一些特征使其難於使用:
· 開發者需要處理大量復雜的任務和基礎結構,例如大量的try-catch-finally-try-catch塊。
· 應用程序需要復雜的錯誤處理以確定連接在使用後被正確關閉,這樣以來使得代碼變得冗長,膨脹,並且重復。
· JDBC中使用了極不明確性的SQLException異常。
· JDBC沒有引入具體的異常子類層次機制。
相應於任何一種錯誤,都只是拋出SQLException異常-無論它來源於JDBC驅動程序還是來源於數據庫,這使得程序員很難理解到底是哪裡實際出現了錯誤。例如,如果SQL對象是無效的或已經被鎖定,那麼將拋出一個SQLException異常。調試這樣的異常需要一定的時間來檢查SQL狀態值和錯誤代碼。更有甚者,SQL狀態值和錯誤代碼的含義在各種數據庫之間都有些差別。
事實證明,編寫JDBC代碼並不是一項容易的工作-存在大量的重復性的工作。為了說明問題,下面是一個例子-使用傳統型JDBC來從數據庫中得到一個可用任務的列表。
package com.spring.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;
public class TraditionalJDBC {
public Vector getTasksNames() {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Vector task = new Vector();
try {
con = getConnection();
pstmt = con.prepareStatement( "select TASKNAME from tasks");
rs = pstmt.executeQuery();
while (rs.next()) {
task.add(rs.getString(1));
}
} catch (SQLException e) {
System.out.println(e);
} finally {
try {
rs.close();
pstmt.close();
con.close();
} catch (SQLException e1) {
System.out.println(e1);
}
}
return task;
}
private Connection getConnection()throws SQLException {
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",
"scott","tiger");
} catch (SQLException sqle) {
System.out.println(sqle);
return null;
}
}
public static void main(String[] args) {
TraditionalJDBC obj = new TraditionalJDBC();
Vector task = obj.getTasksNames();
for (int i = 0; i < task.size(); i++) {
System.out.println(task.elementAt(i));
}
}
}
除了實際查詢數據庫的SQL代碼外,上面的示例中需要巨大數量的例程代碼。getConnection()方法與我們的任務無關,而即使是getTasksNames()方法也僅包含特定於當前任務的兩行代碼。剩下的都是一些普通的復雜的任務代碼。
JDBC的許多積極方面使得它在許多J2SE和J2EE應用程序中仍然占有重要地位。然而,正如你所見,有一些特征使其比我們可能想像的要更難於使用。JDBC這些乏味並且有時挫敗人性的特征已經導致出現了許多公共的可以利用的JDBC抽象框架(例如SQLExecutor和Apache Jakarta Commons DBUtils),還有數不清的自家生產性JDBC應用程序框架。一種公共的可以利用的JDBC抽象框架正是Spring框架的JDBC抽象。