原生的JDBC編程主要分一下幾個步驟:
(原生的JDBC編程指,僅應用java.sql包下的接口和數據庫驅動類編程,而不借助任何框架)
1. 加載JDBC驅動程序;
2. 負責管理JDBC驅動程序的類 DriverManager 會識別加載的驅動程序,用 DriverManager 類的方法 getConnection()來創建一個數據庫連接類的實例對象;
3. 獲取Connection對象的實例,用Connection對象的方法創建一個 Statement 對象實例,執行標准的SQL語句,對數據庫、表進行相關操作。
4. 返回的結果用 ResultSet 類來處理。
5、出現異常時,對事物進行回滾。
示例:
數據庫表:
CREATE TABLE `person` ( `id` int(10) NOT NULL auto_increment, `name` varchar(20) default NULL, `age` int(4) default NULL, PRIMARY KEY (`id`) )
插入和查詢Service類:
package edu.shao.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class UserService { public Connection getConnection() throws ClassNotFoundException, SQLException { // 加載MySQL的JDBC的驅動 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/test"; String username = "root"; String password = "123456"; // 創建與MySQL數據庫的連接類的實例 Connection conn = DriverManager.getConnection(url, username, password); System.out.println("Database connection established"); return conn; } public void save() throws Exception { Connection conn = getConnection(); try { // 禁用自動提交 conn.setAutoCommit(false); System.out.println("默認的事務隔離級別:" + conn.getTransactionIsolation()); // 用conn創建Statement對象類實例 Statement sql_statement = conn.createStatement(); // 插入數據 sql_statement.executeUpdate("insert person values(10,'aabb', 88)"); System.out.println("Insert success"); //錯誤的插入 sql_statement.executeUpdate("insert person values(11,'aabb', 'error')"); System.out.println("Insert success"); //提交事務 conn.commit(); } catch (Exception e) { e.printStackTrace(); if (conn != null){ //事務回滾 conn.rollback(); } } finally { if (conn != null) { // 關閉連接 try { conn.close(); System.out.println("Database connection terminated"); } catch (Exception e) { /* ignore close errors */ } } } } public void query() throws Exception { Connection conn = getConnection(); try { // 用conn創建Statement對象類實例 Statement sql_statement = conn.createStatement(); // 執行查詢,用ResultSet類的對象,返回查詢的結果 String query = "select * from person"; ResultSet result = sql_statement.executeQuery(query); // 處理結果 while (result.next()) { int id = result.getInt("id"); String name = result.getString("name"); String age = result.getString("age"); System.out.println("id: " + id + " name: " + name + " age: " + age); } } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { // 關閉連接 try { conn.close(); System.out.println("Database connection terminated"); } catch (Exception e) { /* ignore close errors */ } } } } }
測試類:
package edu.shao.jdbc; import org.junit.Test; public class JdbcTest { @Test public void testSave() throws Exception{ UserService service=new UserService(); service.save(); } @Test public void testQuery() throws Exception{ UserService service=new UserService(); service.query(); } }
save()方法中,第一個insert操作正確,第二個insert操作是人為的錯誤,我們catch了第二個錯誤,並且把事務回滾。
事務
在數據庫的操作中,事務是一個重要的概念,舉個例子:
大概每個人都有轉賬的經歷。當我們從A帳戶向B帳戶轉100元后,銀行的系統會從A帳戶上扣除100而在B帳戶上加100,這是一般的正常現象。
但是一旦系統出錯了怎么辦呢,這里我們假設可能會發生兩種情況:
(1)A帳戶上少了100元,但是B帳戶卻沒有多100元。
(2)B帳戶多了100元錢,但是A帳戶上卻沒有被扣錢。
這種錯誤一旦發生會造成很嚴重的后果,比如轉賬金額是100萬...
那么有沒有什么方法保證一旦A帳戶上沒有被扣錢而B帳戶上也沒有被加錢;或者A帳戶扣了100元而B帳戶准確無誤的加上100元呢。也就是說要么轉賬順利的成功進行,要么不轉賬呢? 這就是數據庫事務機制所要起到的作用和做的事情。
JDBC對事務的支持
在JDBC的數據庫操作中,一項事務是由一條或是多條表達式所組成的一個不可分割的工作單元。我們通過提交commit()或是回退rollback()來結束事務的操作。關於事務操作的方法都位於接口java.sql.Connection中。
首先我們要注意,在JDBC中,事務操作默認是自動提交。也就是說,一條對數據庫的更新表達式代表一項事務操作。操作成功后,系統將自動調用commit()來提交,否則將調用rollback()來回退。
其次,在JDBC中,可以通過調用setAutoCommit(false)來禁止自動提交。之后就可以把多個數據庫操作的表達式作為一個事務,在操作完成后調用commit()來進行整體提交。倘若其中一個表達式操作失敗,都不會執行到commit(),並且將產生相應的異常。此時就可以在異常捕獲時調用rollback()進行回退。這樣做可以保持多次更新操作后,相關數據的一致性。
上面示例代碼中的save()方法,就是應用了這種方式。
從上面的代碼中,我們可以體會到,應用原生的JDBC訪問數據庫的代碼冗長、重復,容易忘記某一步驟從而導致出錯,並且需要顯示的控制事務。后面,我們將介紹應用spring、hibernate框架提供一種更完善的數據庫訪問的解決方案。
參考:http://fzfx88.iteye.com/blog/110295