標籤:des io os 使用 java ar strong for 檔案
一、JDBC常用介面、類介紹
JDBC提供對獨立於資料庫統一的API,用以執行SQL命令。API常用的類、介面如下:
DriverManager
管理JDBC驅動的服務類,主要通過它擷取Connection資料庫連結,常用方法如下:
public static synchronized Connection getConnection(String url, String user, String password) throws Exception;
該方法獲得url對應的資料庫的串連。
Connection常用資料庫操作方法:
Statement createStatement throws SQLException: 該方法返回一個Statement對象。
PreparedStatement prepareStatement(String sql) throws SQLException;該方法返回先行編譯的Statement對象,
即將SQL語句提交到資料庫進行先行編譯。
CallableStatement prepareCall(String sql) throws SQLException:該方法返回CallableStatement對象,
該對象用於預存程序的調用。
上面的三個方法都是返回執行SQL語句的Statement對象,PreparedStatement、CallableStatement的對象是Statement的子類,
只有獲得Statement之後才可以執行SQL語句。
關於Connection控制事務的方法:
Savepoint setSavepoint(): 建立一個儲存點
Savepoint setSavepoint(String name):建立一個帶有名稱的儲存點
void setTransactionIsolation(int level):設定交易隔離等級
void rollback():復原事務
void rollback(Savepoint savepoint):復原到指定儲存點
void setAutoCommit(boolean autoCommit): 關閉自動認可,開啟事務
void commit():提交事務
Statement
用於執行SQL語句的API介面,該對象可以執行DDL、DCL語句,也可以執行DML語句,
還可以執行SQL查詢語句,當執行查詢語句是返回結果集,常用方法如下:
ResultSet executeQuery(String sql) throws SQLException:該方法用於執行查詢語句,並返回查詢結果對應的ResultSet對象,
該方法只用於查詢語句。
int executeUpdate(String sql) throws SQLException:該方法用於執行DML語句,並返回受影響的行數;
該方法也可以執行DDL,執行DDL返回0;
boolean execute(String sql) throws SQLException:該方法可以執行任何SQL語句,如果執行後第一個結果是ResultSet對象,
則返回true;如果執行後第一個結果為受影響的行數或沒有任何結果,則返回false;
PreparedStatement
先行編譯的statement對象,PreparedStatement是Statement的子介面,它允許資料庫先行編譯SQL(通常指帶參數SQL)語句,
以後每次只改變SQL命令參數,避免資料庫每次都編譯SQL語句,這樣效能就比較好。而相對於Statement而言,
使用PreparedStatement執行SQL語句時,無需重新傳入SQL語句,因為它已經先行編譯了SQL語句。
但是PreparedStatement需要為編譯的SQL語句傳入參數值,所以它比了如下方法:
void setXxx(int index, value)根據該方法傳入的參數值的類型不同,需要使用不同的方法。
傳入的值的類型根據傳入的SQL語句參數而定。
ResultSet
void close() throws SQLException:釋放、關閉ResultSet對象
boolean absolute(int row):將結果集移動到第幾行,如果row是負數,則移動到倒數第幾行。
如果移動到的記錄指標指向一條有效記錄,則該方法返回true;
void beforeFisrt(): 將ResultSet的記錄指標定位到首行之前,這是ResultSet結果集記錄指標的
初始狀態:記錄指標的起始位置位於第一行之前。
boolean first():將ResultSet的記錄指標定位到首行。如果移動後的記錄指標指向一條有效記錄,則該方法返回true。
boolean previous():將ResultSet的記錄指標定位到上一行,如果移動後的記錄指標指向一條有效記錄,則該方法返回true。
boolean next():將ResultSet的記錄指標定位到下一行。如果移動後的記錄指標指向一條有效記錄,則返回true。
boolean last():將ResultSet的記錄指標定位到最後一行。如果移動後的記錄指標指向一條有效記錄,則返回true。
void afterLast():將ResultSet的記錄指標定位到最後一行之後。
注意:在JDK1.4以前只支援next移動,且每次移動一個位置。到JDK1.5就可以隨意定位。
二、JDBC編程步驟
進行jdbc編程步驟大致如下:
1、載入資料庫驅動
Class.forName(driverClass)
上面的dirverClass就是資料庫驅動類所對應的類路徑字串,根據不同資料庫廠商提供的驅動也不同。
2、通過DriverManager擷取資料庫的連結
DriverManager.getConnection(String url, Stirng user, String pass)
當使用DriverManager來擷取連結,需要傳入三個參數:分別是資料量的url、使用者名稱、密碼。
3、通過Connection對象建立Statement對象,Connection建立Statement的方法如下三個:
createStatement()建立基本的Statement對象。
prepareStatement(String sql):根據傳入的sql語句建立先行編譯的Statement對象。
prepareCall(String sql):根據傳入的sql語句建立CallableStatement對象
4、Statement執行SQL語句,Statement有三大方法來執行SQL語句:
execute:可以執行任何SQL語句,單比較麻煩
executeUpdate:可以執行DML、DDL語句。執行DML返回受影響的SQL語句行數,執行DDL返回0;
executeQuery:只能執行查詢語句,執行後返回代表查詢結果的ResultSet對象。
5、操作結果集,針對ResultSet
主要移動指標和獲得值
next、previous、first、last、beforeFrist、afterLast、absolute等移動指標的方法。
getXxx獲得移動指標指向行,特定列、索引的值。使用列名作為擷取值的參數可讀性好、使用索引作為擷取參數效能好。
三、JDBC執行SQL語句
1、 executeUpdate執行DDL、DML語句
Statement提供了execute、executeUpdate、executeQuery三種方法執行,下面用executeUpdate來執行DDL、DML語句,
executeUpdate執行DDL傳回值是0,執行了DML是返回影響後的記錄條數。
2、 execute執行SQL語句
當我們知道SQL語句是完成修改語句時,我們就知道使用executeUpdate語句來完成操作;
如果SQL語句是完成查詢操作的時候,我們就使用executeQuery來完成。
如果我們不知道SQL陳述式完成什麼操作的時候,就可以使用execute方法來完成。
當我們使用Statement對象的execute方法執行SQL語句後返回的是boolean值,這就說明該語句能否返回ResultSet對象。
那麼,如何判斷是否是ResultSet對象?方法如下:
getResultSet():擷取該Statement執行查詢語句返回的ResultSet對象
getUpdateCount():擷取該Statement執行修改語句影響的行數
3、 PrepareStatement執行SQL語句
對於我們操作資料庫的時候,執行某一條SQL語句的時候。只有它的參數不同,而SQL語句相同。
我們可以使用預留位置來設定我們的參數資訊,PrepareStatement中的預留位置是?,用?代替參數的位置。
insert into table values(?, ‘abc’, ?);
預留位置僅僅支援PrepareStatement,而Statement不支援預留位置。PrepareStatement是先行編譯SQL語句的,
然後將佔位符替換成參數。而Statement就不能做到。
PrepareStatement對象也有execute、executeUpdate、executeQuery這三個方法,但這三個方法都無需傳遞參數。
只需用PrepareStatement來設定預留位置的參數,通過用setXxxx(index, value)來完成設定參數資訊即可。
PrepareStatement的效率要比Statement的效率高。
PrepareStatement設定參數可以不拼接字串,而Statement設定參數資訊的時候需要手動拼接字串。
拼接字串容易操作程式錯誤、可讀性降低、維護性升高、程式效能下降。而PrepareStatement直接設定參數
資訊就降低了編程的複雜度。並且它可以放在SQL注入。因為它是通過setXxx方法進行設定參數資訊,
而Statement是通過拼接字串,很容易就造成SQL注入。
綜上所述,PrepareStatement比Statement有以下優點:
先行編譯SQL語句,效能更好
無需拼接SQL語句,編程更簡單
可以防止SQL語句注入,安全性更好
4、 CallableStatement調用預存程序
預存程序的調用可以通過CallableStatement,通過Connection對象的prepareCall方法來建立CallableStatement對象。
然後傳入預存程序的SQL語句,即可調用預存程序,格式如下:
{call proc_name(?, ?, ?)}
上面的?是預留位置,表示傳遞的參數。
預存程序有傳入參數、傳出參數。傳入參數是程程式必須傳入的參數,可以 通過setXxx方法進行設定參數值。
而傳出參數則需要通過程式進行設定,可以用CallableStatement對象的registerOutParameter方法來
註冊輸出參數,cs.registerOutParameter(3, Types.STRING);
設定完畢後,當調用預存程序後要擷取輸出參數值,可以通過getXxx方法來完成。
四、操作結果集(ResultSet)
JDBC是通過ResultSet來管理結果集,操作ResultSet可以通過移動其指標來指向不同的行記錄,然後取出目前記錄即可。並且ResultSet可以完成更新記錄,還提供了ResultSetMetaData來獲得對象相關資訊。
1、 可移動、可更新的ResultSet
前面介紹過ResultSet的相關方法,可以通過一系列的方法來移動記錄指標,
如:absolute、previous、next、first、last、beforeFirst、afterLast等方法。
ResultSet預設是不支援更新的,如果希望ResultSet完成更新操作,必須在建立Statement或PrepareStatement時傳入一些參數。
Connection對象在建立Statement或PrepareStatement時可以傳入兩個參數:
A、 resultSetType:控制ResultSet的類型,該參數有以下三個值:
a、 ResultSet.TYPE_FORWARD_ONLY該常量控制記錄指標只能向前移動。Jdk1.4的預設值
b、 ResultSet.TYPE_SCROLL_INSENSITIVE:該常量控制記錄指標自由移動(可滾動結果集),
但底層的資料改變不影響結果集ResultSet的內容
c、 ResultSet.TYPE_SCROLL_SENSITIVE:該常量控制記錄指標自由移動,但底層資料的影響會改變結果集ResultSet的內容
B、 resultSetConcurrency:控制ResultSet的並發類型,該參數可以接收如下兩個值:
a、 ResultSet.CONCUR_READ_ONLY:該常量表示ResultSet是唯讀併發模式
b、 ResultSet.CONCUR_UPDATABLE:該常量表示ResultSet是更新併發模式
通過PrepareStatement、Statement的建立時進行參數設定來建立可滾動、可更新的ResultSet,
然後通過rs的updateXxx方法來完成某列的更新值設定,通過updateRow來提交修改。
2、 ResultSet中的二進位Blob資料處理
Blob類型通常用來隱藏檔,如:圖片、音頻、視頻檔案。將檔案轉換成二進位儲存在資料庫中,
取出來的時候可以位元據恢複成檔案。
如果要插入圖片到資料庫,顯然不能直接設定SQL參數拼接字串進行插入。因為二進位常量無法表示。
但是將Blob類型資料插入到資料可以用PrepareStatement,通過PrepareStatement對象的setBinaryStatement
方法將參數傳入到二進位輸入資料流;也可以用Blob對象的getBytes方法直接取出資料。
3、 利用ResultSetMetaData操作ResultSet結果集
在我們查詢資料返回的結果集中,我們不清楚結果集存放的資料類型、資料列數。
那樣我們就可以用ResultSetMetaData來讀取ResultSet的資訊。
通過ResultSet的getMetaData()的方法可以擷取ResultSetMetaData對象。
然後可以用ResultSetMetaData對象的方法來操作ResultSet,常用方法如下:
int getColumnCount():返回ResultSet的列名數量
int getColumnType(int column):返回指定索引的類型
String getColumnName(int column):返回指定索引的列名
五、JDBC事務
1、 事務介紹
事務是一步或多步組成操作序列組成的邏輯執行單元,這個序列要麼全部執行,要麼則全部放棄執行。
事務的四個特性:原子性(Atomicity)、一致性(Consistency)、隔離性(IsoIation)和持久性(Durability)
原子性(Atomicity):事務應用最小的執行單元,不可再分。是事務中不可再分的最小邏輯執行體。
一致性(Consistency):事務的執行結果,必須使資料庫的從一個一致性的狀態變到另一個一致性的狀態。
隔離線(IsoIation):各個事務的執行互不干擾,任意一個事務的內部操作對其他並發的事務,都是隔離的。也就是:並發執行的事務之間不能看到對方的中間狀態,並發執行的事務之間不能互相影響。
持久性(Durability):持久性也稱為持久性(Persistence),指事務一旦提交,對資料所做的任何改變,都要記錄到永久儲存空間中,通常就是儲存在物理資料庫中。
通常資料庫的事務涉及到的語句有:
一組DML(Data Munipulation Language,資料操作語言)語句,這組DML語句修改後資料將保持較好的一致性;
動作表的語句,如插入、修改、刪除等;
一個DDL(Data Definition Language,資料定義語言 (Data Definition Language))語句,操作資料對象的語言,有create、alter、drop。
一個DCL(Data Control Language,資料控制語言)語句,主要有grant、revoke語句。
DDL和DCL語句最多隻能有一個,因為它們都會導致事務的立即提交。
當事務所包含的全部資料庫操作都成功執行後,應該提交事務,使這些修改永久生效。
事務提交有兩種方式:顯示提交和自動認可。
顯示提交:使用commit提交
自動認可:執行DLL或DCL,或者程式正常退出
當事務包含的任意一個資料庫操作執行失敗後,應該復原(rollback)事務,使該事務中所作的修改全部失效。
事務的復原方式有兩種:顯示復原和自動復原。
顯示復原:使用rollback
自動復原:系統錯誤或強行退出
2、 JDBC的事物的支援
JDBC的Connection也支援事物,Connection預設開啟自動認可,即關閉事物。
也就是說,每條SQL語句執行就會立即提交到資料庫,永久生效,無法對其進行操作。
關閉Connection的自動認可,開啟事物。Connection的setAutoCommit方法即可:connection.setAutoCommit(false);
通過connection.getAutoCommit()來擷取事物的模式。
當我們開啟事物後,在當前Connection中完成的資料庫操作,都不會立即提交到資料庫,需要調用Connection的commit方法才行。
如果有語句執行失敗,可以調用rollback來復原。
注意:如果Connection遇到未處理的SQLException異常時,系統將非正常退出,系統會自動復原該事務。
如果程式捕捉了該異常,則需要在異常處理中顯示復原事務。
Connection提供了設定事務中間儲存點的方法:setSavepoint,有2個方法可以設定中間點:
Savepoint setSavepoint():在當前事務中建立一個未命名的中間點,並返回該中間點的Savepoint對象。
Savepoint setSavepoint(String name):當前事務中建立一個具有指定名稱的中間點,並返回該中間點的Savepoint對象
通常setSavepoint(String name)設定中間點的名稱,交易回復並不是通過中間點的名稱進行復原的,而是根據中間點對象進行復原的。
設定名稱只是更好的區分中間點對象,用Connection的rollback(Savepoint savepoint)方法即可完成復原到指定中間點。
3、 JDBC的批次更新
批次更新就是可以同時進行多條SQL語句,將會被作為一批操作被同時執行、同時提交。
批次更新需要得到資料底層的支援,可以通過調研DataBaseMetaData的supportsBatchUpdates方法來查看底層資料庫是否支援批次更新。
批次更新也需要建立一個Statement對象,然後通過該對象的addBatch方法將多條SQL語句同時收集在一起,
然後通過Statement對象的executeBatch同時執行這些SQL語句,如下代碼:
Statement sm = conn.createStatement();
sm.addBatch(sql);
sm.addBatch(sql2);
sm.addBatch(sql3);
…
//同時執行多條SQL語句
sm.executeBatch();
執行executeBatch將返回一個int[]的數組,因為使用Statement執行DDL、DML都將返回一個int的值,
而執行多條DDL、DML也將返回一個int數組。批次更新中不允許出現select查詢語句,一旦出現程式將出現異常。
如果要批次更新正確、批量完成,需要用單個事務,如果批次更新過程中有失敗,則需要用交易回復到原始狀態。
如果要達到這樣的效果,需要關閉事務的自動認可,當批次更新完成再提交事務,如果出現異常將復原事務。
然後將串連恢複成自動認可模式。
public int[] executeBatch(String[] sql) throws SQLException {
int[] result = null;
conn = DBHelper.getConnection();
try {
//獲得當前Connection的提交模式
boolean autoCommit = conn.getAutoCommit();
//關閉自動認可模式
conn.setAutoCommit(false);
sm = conn.createStatement();
for (String s : sql) {
sm.addBatch(s);
}
//執行批次更新
result = sm.executeBatch();
//提交事務
conn.commit();
//還原提交模式
conn.setAutoCommit(autoCommit);
} catch (Exception e) {
e.printStackTrace();
conn.rollback();
} finally {
if (sm != null) {
sm.close();
}
DBHelper.close();
}
return result;
}
六、分析資料庫資料
1、 使用DatabaseMetaData分析資料庫資料
JDBC提供了DatabaseMetaData來封裝資料庫連接對應的資料庫資訊,通過Connection的getMetaData方法來擷取該對象。
DatabaseMetaData介面通常資料庫驅動供應商完成實現,其作用是讓使用者瞭解資料庫的底層資訊。
使用該介面可以瞭解資料庫底層的實現,便於完成多個資料庫的相互切換。
如:可以利用supportsCorrelatedSubquenes方法來查看資料庫底層是否可以利用關聯子查詢,
或是調用supportsBatchUpdates方法查看是否支援批次更新。
大部分的DatabaseMetaData都是以ResultSet對象返回的,可以通過ResultSet對象的getString、getInt來擷取相關資訊。
DatabaseMetaData方法都需要傳遞一個xxxPattern的模式字串,這個字串是過濾條件,一般傳遞是SQL中的%、_等內容。
如果傳遞一個null表示不作任何過濾。
Java JDBC 基礎知識