程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> JDBC詳細的入門介紹

JDBC詳細的入門介紹

編輯:JAVA編程入門知識

一、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,數據定義語言)語句,操作數據對象的語言,有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表示不作任何過濾。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved