JDBC數(shù)據(jù)庫連接
導(dǎo)入JDBC包:使用Java語言的import語句在Java代碼開頭位置導(dǎo)入所需的類。
-
注冊JDBC驅(qū)動程序:使JVM將所需的驅(qū)動程序?qū)崿F(xiàn)加載到內(nèi)存中产阱,從而可以滿足JDBC請求。
- 方法I - Class.forName()
注冊驅(qū)動程序最常見的方法是使用Java的Class.forName()方法,將驅(qū)動程序的類文件動態(tài)加載到內(nèi)存中义屏,并將其自動注冊。這個方法是推薦使用的方法蜂大,因為它使驅(qū)動程序注冊可配置和便攜闽铐。 - 方法II - DriverManager.registerDriver()
如果使用的是非JDK兼容的JVM(如Microsoft提供的),則應(yīng)使用registerDriver()方法县爬。
- 方法I - Class.forName()
數(shù)據(jù)庫URL配置:創(chuàng)建一個正確格式化的地址阳啥,指向要連接到的數(shù)據(jù)庫(如:MySQL,Oracle和MSSQL等等)。
創(chuàng)建連接對象:最后财喳,調(diào)用DriverManager對象的getConnection()方法來建立實際的數(shù)據(jù)庫連接察迟。
JDBC Statements, PreparedStatement和CallableStatement語句
Statement對象
-
創(chuàng)建Statement對象
在使用Statement對象執(zhí)行SQL語句之前,需要使用Connection對象的createStatement()方法創(chuàng)建一個Statement對象
在創(chuàng)建Statement對象后耳高,可以使用它來執(zhí)行一個SQL語句扎瓶,它有三個執(zhí)行方法可以執(zhí)行。它們分別是 :- boolean execute (String SQL) : 如果可以檢索到ResultSet對象泌枪,則返回一個布爾值true; 否則返回false概荷。使用此方法執(zhí)行SQLDDL語句或需要使用真正的動態(tài)SQL,可使用于執(zhí)行創(chuàng)建數(shù)據(jù)庫碌燕,創(chuàng)建表的SQL語句等等误证。
- int executeUpdate (String SQL): 返回受SQL語句執(zhí)行影響的行數(shù)。使用此方法執(zhí)行預(yù)期會影響多行的SQL語句修壕,例如:INSERT愈捅,UPDATE或DELETE語句。
- ResultSet executeQuery(String SQL):返回一個ResultSet對象慈鸠。 當您希望獲得結(jié)果集時蓝谨,請使用此方法,就像使用SELECT語句一樣。
關(guān)閉Statement對象
tatement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
stmt.close();
}
PreparedStatement對象
PreparedStatement接口擴展了Statement接口譬巫,它添加了比Statement對象更好一些優(yōu)點的功能咖楣。此語句可以動態(tài)地提供/接受參數(shù)。
創(chuàng)建PreparedStatement對象
JDBC中的所有參數(shù)都由 ? 符號作為占位符芦昔,這被稱為參數(shù)標記诱贿。 在執(zhí)行SQL語句之前,必須為每個參數(shù)(占位符)提供值咕缎。
setXXX()方法將值綁定到參數(shù)瘪松,其中XXX表示要綁定到輸入?yún)?shù)的值的Java數(shù)據(jù)類型。 如果忘記提供綁定值锨阿,則將會拋出一個SQLException宵睦。
每個參數(shù)標記是它其順序位置引用。第一個標記表示位置1墅诡,下一個位置2等等壳嚎。 該方法與Java數(shù)組索引不同(它不從0開始)。
所有Statement對象與數(shù)據(jù)庫交互的方法(a)execute()末早,(b)executeQuery()和(c)executeUpdate()也可以用于PreparedStatement對象烟馅。 但是,這些方法被修改為可以使用輸入?yún)?shù)的SQL語句然磷。關(guān)閉PreparedStatement對象
CallableStatement對象
類似Connection對象創(chuàng)建Statement和PreparedStatement對象一樣郑趁,它還可以使用同樣的方式創(chuàng)建CallableStatement對象,該對象將用于執(zhí)行對數(shù)據(jù)庫存儲過程的調(diào)用姿搜。
JDBC結(jié)果集
SQL語句執(zhí)行后從數(shù)據(jù)庫查詢讀取數(shù)據(jù)寡润,返回的數(shù)據(jù)放在結(jié)果集中。 SELECT語句用于從數(shù)據(jù)庫中選擇行并在結(jié)果集中查看它們的標準方法舅柜。 java.sql.ResultSet接口表示數(shù)據(jù)庫查詢的結(jié)果集梭纹。
ResultSet對象維護指向結(jié)果集中當前行的游標。 術(shù)語“結(jié)果集”是指包含在ResultSet對象中的行和列數(shù)據(jù)致份。
ResultSet接口的方法可以分為三類:
- 瀏覽方法:用于移動光標变抽。
- 獲取方法:用于查看光標指向的當前行的列中的數(shù)據(jù)。
- 更新方法:用于更新當前行的列中的數(shù)據(jù)氮块。 然后在基礎(chǔ)數(shù)據(jù)庫中更新數(shù)據(jù)绍载。
光標可以基于ResultSet的屬性移動。當創(chuàng)建生成ResultSet的相應(yīng)Statement時滔蝉,將指定這些屬性击儡。
JDBC提供以下連接方法來創(chuàng)建具有所需ResultSet的語句
- createStatement(int RSType, int RSConcurrency);
- prepareStatement(String SQL, int RSType, int RSConcurrency);
- prepareCall(String sql, int RSType, int RSConcurrency);
第一個參數(shù)表示ResultSet對象的類型,第二個參數(shù)是兩個ResultSet常量之一锰提,用于指定結(jié)果集是只讀還是可更新曙痘。
JDBC事務(wù)
如果JDBC連接處于自動提交模式,默認情況下立肘,則每個SQL語句在完成后都會提交到數(shù)據(jù)庫边坤。
對于簡單的應(yīng)用程序可能沒有問題,但是有三個原因需要考慮是否關(guān)閉自動提交并管理自己的事務(wù) :
- 提高性能
- 保持業(yè)務(wù)流程的完整性
- 使用分布式事務(wù)
事務(wù)能夠控制何時更改提交并應(yīng)用于數(shù)據(jù)庫谅年。 它將單個SQL語句或一組SQL語句視為一個邏輯單元茧痒,如果任何語句失敗,整個事務(wù)將失敗融蹂。
要啟用手動事務(wù)支持旺订,而不是使用JDBC驅(qū)動程序默認使用的自動提交模式,請調(diào)用Connection對象的setAutoCommit()方法超燃。 如果將布爾的false傳遞給setAutoCommit()区拳,則關(guān)閉自動提交。 也可以傳遞一個布爾值true來重新打開它意乓。
例如樱调,如果有一個名為conn的Connection對象,請將以下代碼關(guān)閉自動提交 -
conn.setAutoCommit(false);
提交和回滾
try{
//Assume a valid connection object conn
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
String SQL = "INSERT INTO Employees " +
"VALUES (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL);
//Submit a malformed SQL statement that breaks
String SQL = "INSERTED IN Employees " +
"VALUES (107, 22, 'Sita', 'Singh')";
stmt.executeUpdate(SQL);
// If there is no error.
conn.commit();
}catch(SQLException se){
// If there is any error.
conn.rollback();
}
使用保存點
設(shè)置保存點(Savepoint)時届良,可以在事務(wù)中定義邏輯回滾點笆凌。
如果通過保存點(Savepoint)發(fā)生錯誤時,則可以使用回滾方法來撤消所有更改或僅保存保存點之后所做的更改士葫。
有一個rollback (String savepointName)方法乞而,它將使用事務(wù)回滾到指定的保存點。
JDBC批量處理
批量處理允許將相關(guān)的SQL語句分組到批處理中慢显,并通過對數(shù)據(jù)庫的一次調(diào)用來提交它們爪模,一次執(zhí)行完成與數(shù)據(jù)庫之間的交互。一次向數(shù)據(jù)庫發(fā)送多個SQL語句時荚藻,可以減少通信開銷呻右,從而提高性能。不需要JDBC驅(qū)動程序來支持此功能鞋喇。應(yīng)該使用DatabaseMetaData.supportsBatchUpdates()
方法來確定目標數(shù)據(jù)庫是否支持批量更新處理声滥。如果JDBC驅(qū)動程序支持此功能,該方法將返回true侦香。
Statement落塑,PreparedStatement和CallableStatement的addBatch()方法用于將單個語句添加到批處理。 executeBatch()用于執(zhí)行組成批量的所有語句罐韩。
executeBatch()返回一個整數(shù)數(shù)組憾赁,數(shù)組的每個元素表示相應(yīng)更新語句的更新計數(shù)。就像將批處理語句添加到處理中一樣散吵,可以使用clearBatch()方法刪除它們龙考。此方法將刪除所有使用addBatch()方法添加的語句蟆肆。 但是,無法指定選擇某個要刪除的語句晦款。
使用Statement對象進行批處理
以下是使用Statement對象的批處理的典型步驟序列:
- 使用createStatement()方法創(chuàng)建Statement對象炎功。
- 使用setAutoCommit()將自動提交設(shè)置為false。
- 使用addBatch()方法在創(chuàng)建的Statement對象上添加SQL語句到批處理中缓溅。
- 在創(chuàng)建的Statement對象上使用executeBatch()方法執(zhí)行所有SQL語句蛇损。
- 最后,使用commit()方法提交所有更改坛怪。
實例:
// Create statement object
Statement stmt = conn.createStatement();
// Set auto-commit to false
conn.setAutoCommit(false);
// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
"VALUES(200,'Ruby', 'Yang', 30)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);
// Create one more SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
"VALUES(201,'Java', 'Lee', 35)";
// Add above SQL statement in the batch.
stmt.addBatch(SQL);
// Create an int[] to hold returned values
int[] count = stmt.executeBatch();
//Explicitly commit statements to apply changes
conn.commit();
使用PrepareStatement對象進行批處理
// Create SQL statement
String SQL = "INSERT INTO Employees (id, first, last, age) " +
"VALUES(?, ?, ?, ?)";
// Create PrepareStatement object
PreparedStatemen pstmt = conn.prepareStatement(SQL);
//Set auto-commit to false
conn.setAutoCommit(false);
// Set the variables
pstmt.setInt( 1, 400 );
pstmt.setString( 2, "JDBC" );
pstmt.setString( 3, "Li" );
pstmt.setInt( 4, 33 );
// Add it to the batch
pstmt.addBatch();
// Set the variables
pstmt.setInt( 1, 401 );
pstmt.setString( 2, "CSharp" );
pstmt.setString( 3, "Liang" );
pstmt.setInt( 4, 31 );
// Add it to the batch
pstmt.addBatch();
//add more batches
//Create an int[] to hold returned values
int[] count = stmt.executeBatch();
//Explicitly commit statements to apply changes
conn.commit();