Posted on 2005-11-15 12:30
canonical 閱讀(273)
評論(0) 編輯 收藏 所屬分類:
Witrix開發平臺
在witrix平臺中訪問數據庫最直接的方法是使用edu.thu.db.SQL類。基本用法如下:
// 設定數據庫連接參數, 連接可以通過java.sql.DriverManager 和
//javax.sql.DataSource等多種方式建立,并支持數據庫連接緩沖池。
TransactionMode db = new TransactionMode("default"); // 設定數據庫連接參數
SQL sql = SQL.begin().select().field("id")
.from().table("other_table")
.where().like("name","a%");
.end();
int n = SQL.begin().select().countAll()
.from().table("my_table")
.where().gt("value", new Integer(3)) // value > 3
.and().in("type", new String[]{"a","b"}) // type in ('a','b')
.and().in("data_id",sql) // data_id in (select id from
other_table where name like 'a%')
.end().query(db).intValue();
在SQL類的設計中體現了三個設計原則:
1. 正交化的流式設計
2. 參數對象化
3. bug-free設計
首先,SQL類將構造SQL語句,連接數據庫以及查詢結果類型轉換分解成了三個正交的部分。
在一般的數據庫編程中,我們需要如下訪問方式:
String sql = "select count(*) from my_table where value > ?";
Connection conn = getConnection();
PreparedStatement stmt = null;
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setParameter(1, valueLimit);
ResultSet rs = stmt.executeQuery();
rs.next();
int ret = rs.getInt(1);
// ...
}finally{
try{
if(stmt != null)
stmt.close();
}catch(Exception e){
e.printStackTrace();
}
try{
conn.close();
}catch(Exception e){
e.printStackTrace();
}
}
從
以上的例子中,我們可以注意到,在普通JDBC編程中,設置SQL語句的參數,建立數據庫連接,取得結果集中的結果并轉化為合適的格式這三者之間是交織在
一起的。特別是打開連接需要配對的關閉連接語句,造成整個程序的流程不是線性的,
因為我們不能說建立連接之后就可以不再管連接的事情了,我們必須記住在做完所有其他事情之后還要關閉連接。
通過一系列的封裝對象,SQL類實現了一種正交化的流式設計,其分解模式如下:
SQL.begin().拼接SQL語句.end().建立連接并運行SQL語句.轉化結果()
注意在SQL語句執行之后是不需要顯式關閉連接的。
SQL類的第二個設計要點是參數對象化。在witrix平臺中,實際運行SQL語句的引擎函數是
IDbEngine.execute(String sqlText, List sqlParameters, int resultType, int concurrency);
這
里sqlText,
sqlParameters等都是參數,但是在應用中構造這些參數的過程很復雜,并且非常靈活,一般的Util類(靜態Utility函數)無法提供有效
的簡化。
所以構造SQL語句這個過程不是通過util類完成的,而是通過一個專用的SqlBuilder對象。SQL的基本思想是將sql語句納入java程序框
架,使得sql語句成為程序中可控制的部分。首先SQL類將sql文本與sql參數封裝為一個完整的對象,使得sql語句的重用成為可能。其次,
SqlBuilder類通過一種可控制的方式構造sql語句(所有的關鍵字都對應于一個函數),整個過程與直接書寫sql文本類似,但函數封裝使得我們能
夠在同一行上指定sql文本中用到的參數,而不是象jdbc里那樣,集中指定參數。同時SqlBuilder支持面向java語言的擴展,如直接支持
java集合類型等,從而大大簡化了sql語句的構造,因為一般sql拼接中最混亂的部分就是牽涉到循環與判斷。
參數對象化的方法還可以應用于那些具有大量缺省參數的地方。在SQL類中,如果我們希望以scroll insensitive的方式選出數據,調用方式如下:
SQL.begin().select().star()
.from().table("my_table")
.end().scrollable(true).list(db,3,100);
如果我們希望利用Statement.cancel()特性,我們可以指定cancelMonitor參數
SQL.begin()....end().cancelMonitor(monitor).query(db).listValue();
SQL
類的第三個設計要點是bug-free。jdbc中最常出現的錯誤是忘記關閉連接造成資源泄漏,在SQL類中,連接只在需要時才從緩沖池中獲取,當數據庫
操作完成(無論成功或失敗)時,數據庫連接會被自動關閉(或返回連接池),并自動處理提交和回滾的情況。整個程序代碼中一般沒有需要顯式關閉連接的要求,
從而極大的降低了資源泄漏的幾率,避免了這個錯誤的出現。這就如同java沒有要求程序員顯式釋放內存,從而在絕大多數情況下避免了memory
leak的bug一樣。