原生的JDBC編程主要分一下幾個步驟:java
(原生的JDBC編程指,僅應用java.sql包下的接口和數據庫驅動類編程,而不借助任何框架)mysql
1. 加載JDBC驅動程序;spring
2. 負責管理JDBC驅動程序的類 DriverManager 會識別加載的驅動程序,用 DriverManager 類的方法 getConnection()來建立一個數據庫鏈接類的實例對象;sql
3. 獲取Connection對象的實例,用Connection對象的方法建立一個 Statement 對象實例,執行標準的SQL語句,對數據庫、表進行相關操做。數據庫
4. 返回的結果用 ResultSet 類來處理。編程
五、出現異常時,對事物進行回滾。框架
數據庫表:測試
CREATE TABLE `person` ( `id` int(10) NOT NULL auto_increment, `name` varchar(20) default NULL, `age` int(4) default NULL, PRIMARY KEY (`id`) )
插入和查詢Service類:url
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 */ } } } } }
測試類:spa
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的數據庫操做中,一項事務是由一條或是多條表達式所組成的一個不可分割的工做單元。咱們經過提交commit()或是回退rollback()來結束事務的操做。關於事務操做的方法都位於接口java.sql.Connection中。
首先咱們要注意,在JDBC中,事務操做默認是自動提交。也就是說,一條對數據庫的更新表達式表明一項事務操做。操做成功後,系統將自動調用commit()來提交,不然將調用rollback()來回退。
其次,在JDBC中,能夠經過調用setAutoCommit(false)來禁止自動提交。以後就能夠把多個數據庫操做的表達式做爲一個事務,在操做完成後調用commit()來進行總體提交。假若其中一個表達式操做失敗,都不會執行到commit(),而且將產生相應的異常。此時就能夠在異常捕獲時調用rollback()進行回退。這樣作能夠保持屢次更新操做後,相關數據的一致性。
上面示例代碼中的save()方法,就是應用了這種方式。
從上面的代碼中,咱們能夠體會到,應用原生的JDBC訪問數據庫的代碼冗長、重複,容易忘記某一步驟從而致使出錯,而且須要顯示的控制事務。後面,咱們將介紹應用spring、hibernate框架提供一種更完善的數據庫訪問的解決方案。