1. 程式人生 > 其它 >【Java學習筆記(一百二十)】之JDBC程式設計介紹

【Java學習筆記(一百二十)】之JDBC程式設計介紹

技術標籤:Java學習筆記# JavaEE資料庫java

本文章由公號【開發小鴿】釋出!歡迎關注!!!


老規矩–妹妹鎮樓:

一. 資料庫程式設計

(一) 概述

Java資料庫連線(JDBC)API在1996年釋出,開發者通過這個API介面連線到資料庫,並使用結構化查詢語言(SQL)完成對資料庫的操作。

(二) JDBC驅動

1. 概述

由於多個數據庫供應商提供的協議無法統一,因此Java為SQL訪問提供了一套純Java API,即與資料庫無關的API,並且提供了一個驅動管理器,以允許第三方驅動程式註冊到驅動管理器中,並且可以連線到特定的資料庫。通過API編寫的程式都可以與驅動管理器進行通訊,而驅動管理器可以通過驅動程式與實際的資料庫進行通訊。JDBC的驅動遵循了微軟的ODBC,ODBC為C語言訪問資料庫提供了一套程式設計介面。


2. 驅動分類

(1) 將JDBC翻譯為ODBC,使用ODBC驅動與資料庫通訊,即JDBC/ODBC橋。

(2) 由部分Java程式和部分原生代碼構成,用於與資料庫的客戶端API進行通訊,使用這種驅動之前,不僅需要安裝Java類庫,還要安裝平臺相關的程式碼。

(3) 純Java客戶端類庫,使用一種與具體資料庫無關的協議將資料庫請求傳送給伺服器構件,然後構件將資料庫請求翻譯成資料庫相關的協議。

(4) 純Java類庫,將JDBC請求直接翻譯為資料庫相關的協議。

3. JDBC的典型用法

傳統的C/S架構中,在伺服器端部署資料庫,將JDBC驅動部署在客戶端。如今的三層模型中,客戶端不直接呼叫資料庫,而是呼叫伺服器上的中介軟體層,由中介軟體層完成資料庫查詢操作。這種模型可以將視覺化表示(客戶端)從業務邏輯(中間層)和原始資料(資料庫)中分類出來,即客戶端可以有多種表現形式。


(三) JDBC配置

1. 註冊驅動器類

許多JDBC的JAR檔案會自動註冊驅動器類,當然我們也可以手動註冊,首先找出該驅動類的全限定名,通過使用DriverManager,用兩種方式來註冊驅動器。一種是在Java程式中載入驅動器類,即執行註冊驅動器的靜態初始化器,如:

Class.forName(“org.postgresql.Driver”);

另一種方式是設定jdbc.drivers屬性,可以使用命令列引數來指定這個屬性,如:

java -Djdbc.drivers=org.postgresql.Driver Name

或者在應用中設定系統屬性,如:

System.
setProperty(“jdbc.drivers”, “org.postgresql.Driver”);

(四) 使用JDBC語句

1. 建立Connection物件

首先通過DriverManager建立連線物件Connection,如下所示:

Connection conn = DriverManager.getConnection(url ,username, password);

2. 建立Statement物件

然後建立Statement語句物件,執行各種SQL語句。每個Connection物件可以建立多個Statement物件,同一個Statement物件可以用於多個不相關的命令和查詢,但是一個Statement物件最多隻能有一個開啟的結果集。我們需要確保在一個Statement物件觸發新的查詢或更新語句之前結束對所有結果集的處理,因為前序查詢的所有結果集都會被自動關閉。使用try(){}語句塊來自動關閉物件。

Statement stat = conn.createStatement();

3. 執行SQL語句

通過Statement物件執行SQL語句。

(1) executeQuery(command)

SELECT查詢操作,返回一個ResultSet型別物件,可以通過它來每次一行地迭代遍歷所有查詢結果。

ResultSet rs = stat.executeQuery(“SELECT * FROM Books”);

結果集中行的順序是任意排列的,除非使用ORDER BY 子句指定行的順序,否則行順序是沒有意義的。獲取結果集後,通過訪問器方法來獲取其中的資訊,每個訪問器都有兩種形式,一種接受數字型引數,另一種接受字串引數,資料庫的列序號是從1開始計算的。

String isbn = rs.getString(1);
double price = rs.getDouble(“Price”);

(五) 執行查詢操作

1. 預備語句

我們沒有必要在每次進行查詢時都建立新的查詢語句,可以準備一個帶有宿主變數的查詢語句,每次查詢時只需要為該變數填入不同的字串就可以反覆使用。每個宿主變數使用“?”來表示,如下所示:

String statement = “SELECT * FROM tb_name WHERE id=?;
PreparedStatement stat = conn.prepareStatement(statement);

執行預備語句之前,必須使用set方法將變數繫結到實際的值上,第一個引數是宿主變數的位置,即第幾個變數,第二個引數為變數的值。

stat.setString(1,3);

由於字串拼接有潛在的危險,如引號這樣的字元或者使用者的輸入可能會導致的注入攻擊,因此只要查詢涉及變數就應該使用預備語句。當Connection物件關閉後,相關的預備語句也就失效了。

2. 讀寫LOB

資料還可以儲存大物件,如圖片或者其他資料,在SQL中,二進位制大物件稱為BLOB,字元型大物件稱為CLOB。要讀取LOB,需要執行SELECT語句,然後在ResultSet上呼叫getBlob或getClob方法,這樣就可以獲得Blob或者Clob型別的物件了。

try(ResultSet result = stat.executeQuery()){
	if(result.next()){
		Blob coverBlob = result.getBlob();
		Image coverImage = ImageIO.read(coverBlob.getBinaryStream());
	}
}

要將LOB置於資料庫中,需要在Connection物件上呼叫createBlob或者createBlob,然後獲取一個用於該LOB的輸出流或寫出器,寫出資料,並將該物件儲存到資料庫中。

3. 獲取自動生成的鍵

大多數資料庫都支援在資料庫中對行自動編號的機制,這些自動編號的值通過作為主鍵,儘管JDBC沒有提供獨立於提供商的自動生成鍵的解決方案,但是提供了獲取自動生成建的途徑,當插入一個新行,該行的鍵自動生成時,我們可以這樣來獲取:

stat.executeUpdate(insertStatement, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stat.getGeneratedKeys();
if(rs.next()){
	int key = rs.getInt(1);
}

(六) 可滾動和可更新的結果集

1. 可滾動的結果集

預設的結果集是不可滾動和不可更新的,可以通過Statement物件的設定來獲取不同的結果集。

Statement stat = conn.createStatement(type, concurrency);

type有三種類型:

(1) TYPE_FORWARD_ONLY

不能滾動

(2) TYPE_SCROLL_INSENSITIVE

可以滾動,但對資料庫變化不敏感,即不會實時更新資料庫。

(3) TYPE_SCROLL_SENSITIVE

可以滾動,對資料庫變化敏感。

concurrency兩種型別:

(1) CONCUR_READ_ONLY

結果集不能用於更新資料庫。

(2) CONCUR_UPDATABLE

結果集可以用於更新資料庫。


2. 可更新的結果集

如果希望編輯結果集中的資料,並且將結果集中的資料變更自動反應到資料庫中,那麼需要使用可更新的結果集。

Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

(七) 行集

客戶端與資料庫的連線並不一定是高效的,很多時候連線資源是浪費的,因此我們使用行集來解決這個問題。RowSet介面擴充套件自ResultSet介面,但無需使用保持與資料庫的連結。

1. 構建行集

RowSetFactory fac = RowSetProvider.newFactory();
CachedRowSet crs = fac.createCachedRowSet();

有好幾種行集型別,都擴充套件了RowSet介面。

2. 被快取的行集

一個被快取的行集中包含了一個結果集中所有的資料,斷開資料庫後依然可以使用行集,同時可以修改行集中的資料,再通過顯示的請求傳送到資料庫中更新修改。

(八) 元資料

JDBC還提供了關於資料庫以及其表結構的詳細資訊,即元資料,區別於資料庫中儲存的實際資料,我們可以獲取三類元資料,一類是資料庫的元資料,一類是結果集的元資料,一類是預備語句引數的元資料。通過從資料庫連線中獲取一個DatabaseMetaData物件來獲取元資料。


(九) 事務

1. 概述

一組語句構成一個事務,當所有語句都順利執行後,事務可以被提交,否則如果其中某個語句遇到錯誤,那麼事務將被回滾,就好像沒有語句被執行過一樣。


2. JDBC事務程式設計

預設情況下,資料庫連線處於自動提交模式,即每個SQL語句一旦被執行就會被提交給資料庫,一旦命令被提交,就無法對它進行回滾操作,在使用事務時,要關閉這個預設值。

conn.setAutoCommit(false);

conn.commit();
conn.rollback();

3. 儲存點

在使用某些驅動程式時,使用儲存點來更細粒度地控制回滾操作,建立一個儲存點即意味著只需要返回到這個點,而不是放棄整個事務。當不需要儲存點時,釋放它。

Statement stat = conn.createStatement();
state.executeUpdate(command1);
Savepoint svpt = conn.setSavepoint();
stat.execcuteUpdate(command2);
if() conn.rollback(svpt);
conn.commit();
conn.releaseSavepoint(svpt);

(十) 資料庫連線池機制

JDBC規範中為實現者提供了用以實現連線池服務的手段,但是JDK並沒有實現資料庫連線池,JDBC驅動中通常也不包含這項服務,相反,WEB容器和應用伺服器的開發商會提供連線池服務的實現。連線池的機制通常還可以用於預備語句上。