最近寫程序已經(jīng)很少直接用JDBC了,一直都是用ibaits, Hibernate等來招呼,因?yàn)楝F(xiàn)在的集成框架已經(jīng)很穩(wěn)定了。不過對JDBC的直接使用還是不可以忽略的,JDBC3.0提供的n多的新特征還是要熟悉了解的,以前學(xué)jdbc的時(shí)候就是上網(wǎng)找些demo和介紹來學(xué),使用很單一,對JDBC3.0的好多新的特征都忽略了,比如下面一個(gè)例子:
Statement stmt = con.createStatement();
ResultSet rs =
stmt.executeQuery("SELECT * FROM user WHERE
username='aa'");
stmt.executeUpdate("UPDATE user SET lastdatetime=now() where
username='aa'");
這是一個(gè)用戶登錄時(shí),經(jīng)常用到的代碼,先是根據(jù)用戶名aa查找該用戶的詳細(xì)信息,然后再更新該用戶的最后登錄時(shí)間(lastdatetime)。這這個(gè)里面,我們用了兩個(gè)sql語句,這個(gè)是我一直用的方法,但是如果用JDBC2.0給我們提供的便利,我們只要寫一條sql就夠了,其他的都交給jdbc,看下面的代碼:
Statement stmt2 =
con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet
rs2 = stmt.executeQuery("SELECT * FROM user WHERE
username='aa'");
rs2.next();
rs2.updateDate("lastdatetime", new
Date(Calendar.getInstance().getTimeInMillis()));
rs2.updateRow();
這里面最主要的特征就是ResultSet.TYPE_FORWARD_ONLY和ResultSet.CONCUR_UPDATABLE,通過初始化Statement時(shí)傳不同的參數(shù),可以對ResultSet進(jìn)行不用的錯(cuò)作限制。con.createStatement的時(shí)候,有三種可以掉用的函數(shù):
1、createStatement();
2、createStatement(int resultSetType, int
resultSetConcurrency)
3、createStatement(int resultSetType, int
resultSetConcurrency, int resultSetHoldability)
其中resultSetType可選值是:
?? 1、ResultSet.TYPE_FORWARD_ONLY?
在ResultSet中只能先前移動游標(biāo),
?? 2、ResultSet.TYPE_SCROLL_INSENSITIVE
在ResultSet中可以隨心所欲的先前向后移動游標(biāo),
?? 3、ResultSet.TYPE_SCROLL_SENSITIVE
在ResultSet中可以隨心所欲的先前向后移動游標(biāo),同時(shí)ResultSet的值有所改變的時(shí)候,他可以得到改變后的最新的值
其中resultSetConcurrency可選值是:
??
1、ResultSet.CONCUR_READ_ONLY? 在ResultSet中的數(shù)據(jù)記錄是只讀的,可以修改
??
2、ResultSet.CONCUR_UPDATABLE?
在ResultSet中的數(shù)據(jù)記錄可以任意修改,然后更新會數(shù)據(jù)庫
其中resultSetHoldability可選值是:
??
1、ResultSet.HOLD_CURSORS_OVER_COMMIT 表示修改提交時(shí),不關(guān)閉ResultSet的游標(biāo)
??
2、ResultSet.CLOSE_CURSORS_AT_COMMIT? 表示修改提交時(shí),關(guān)閉ResultSet的游標(biāo)
對于查詢操作第一種初始化方法createStatement(),相當(dāng)于第二種方法的createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY),第三種方法的createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT)
下面寫一段demo的代碼,我把一些特征函數(shù)都用出來,但是只是用來查考和說明名靈活性的。
?Statement stmt2 =
con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
?ResultSet
rs2 = stmt.executeQuery("SELECT * FROM
user");
?rs2.next();
?rs2.updateDate("lastdatetime", new
Date(Calendar.getInstance().getTimeInMillis()));
?rs2.updateRow();
?rs2.afterLast();
?while(rs2.previous()){
/**....*/ }
?rs.beforeFirst();
?while(rs2.next()){? /**....*/
}
?rs.last();
?rs.first();
?rs.absolute(5);?//游標(biāo)移動到第5條
?rs.absolute(-1);?
//游標(biāo)移動到最后一條
?rs.relative(-5);? //游標(biāo)向上移動5條
?rs.relative(2);??
//游標(biāo)向下移動2條
?rs.deleteRow();?//刪除當(dāng)前行
?rs.last();?
//游標(biāo)移動到最后
?rs.updateString("summary", "This is ...");
//設(shè)置更新的字段值
?rs.cancelRowUpdates();? //取消剛才輸入的更新
?rs.getRow();
//得到當(dāng)前行號
?rs.moveToInsertRow();? //游標(biāo)移動到要新增的那條記錄上
?rs.updateInt("id",
1);
?rs.updateString(2, "my name");
?rs.insertRow(); //插入新記錄
JDBC2.0提供的還有一個(gè)功能就是數(shù)據(jù)庫的批量操作:
??con.setAutoCommit(false);
??Statement stmt3 =
con.createStatement();
??stmt3.addBatch("insert
.....");
??stmt3.addBatch("insert .....");
??int[] rows =
stmt3.executeBatch();
??con.commit();
但是有一點(diǎn)要注意,stmt3.executeBatch()他不會自動給你回滾數(shù)據(jù)操作,當(dāng)你有5條update語句的時(shí)候,如果第三條發(fā)生錯(cuò)誤,那么將無法自動回滾前兩條update語句的影響,所以一定要自己手工進(jìn)行事務(wù)管理。
在您的事務(wù)中使用 Savepoint
JDBC3.0中最令人興奮的附加特點(diǎn)就是 Savepoint
了。有時(shí)候需要的是對事務(wù)多一點(diǎn)的控制,而不是在當(dāng)前的事務(wù)中簡單地對每一個(gè)改變進(jìn)行回滾。在JDBC3.0下,您就可以通過 Savepoint
獲得這種控制。Savepoint 接口允許您將事務(wù)分割為各個(gè)邏輯斷點(diǎn),以控制有多少事務(wù)需要回滾??聪旅娴拇a:
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate(
"INSERT INTO authors (first_name, last_name) valueS(′Lewis′, ′Carroll′)");
Savepoint svpt = conn.setSavepoint("NewAuthor");
try{
?rows =
stmt.executeUpdate( "UPDATE authors set type = ′fiction′ WHERE last_name =
′Carroll′");
}catch(Exception e){
?conn.rollback(svpt);
?rows =
stmt.executeUpdate( " update .......... other sql ");
}
conn.commit();
上面代碼顯示,當(dāng)UPDATE authors失敗的時(shí)候,系統(tǒng)事務(wù)回滾UPDATE authors的sql的影響,而INSERT INTO authors的sql仍然有效
檢索自動產(chǎn)生的關(guān)鍵字
為了解決對獲取自動產(chǎn)生的或自動增加的關(guān)鍵字的值的需求,JDBC
3.0現(xiàn)在將獲取這種值變得很輕松。要確定任何所產(chǎn)生的關(guān)鍵字的值,只要簡單地在語句的 execute()
方法中指定一個(gè)可選的標(biāo)記,Statement.RETURN_GENERATED_KEYS和Statement.NO_GENERATED_KEYS。在執(zhí)行這條語句后,所產(chǎn)生的關(guān)鍵字的值就會通過從
Statement 的實(shí)例方法 getGeneratedKeys() 來檢索 ResultSet 而獲得。ResultSet
包含了每個(gè)所產(chǎn)生的關(guān)鍵字的列??聪旅娲a:
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO authors (first_name, last_name) valueS
(′George′, ′Orwell′)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs =
stmt.getGeneratedKeys();
if ( rs.next() ) {
?int key = rs.getInt();
}
?參考資料: http://java.sun.com/j2se/1.5.0/docs/api/java/sql/package-summary.html