【聲明】 html
歡迎轉載,但請保留文章原始出處→_→ java
生命壹號:http://www.cnblogs.com/smyhvae/mysql
文章來源:http://www.cnblogs.com/smyhvae/p/4055183.htmlsql
【正文】數據庫
首先須要回顧一下上一篇文章中的內容:MySQL數據庫學習筆記(九)----JDBC的PreparedStatement接口重構增刪改查設計模式
1、JDBC事務處理:ide
咱們已經知道,事務的概念即:全部的操做要麼同時成功,要麼同時失敗。在MySQL中提供了Commit、Rollback命令進行事務的提交與回滾。實際上在JDBC中也存在事務處理,若是要想進行事務處理的話,則必須按照如下的步驟完成。工具
JDBC中事務處理的步驟:學習
一、要取消掉JDBC的自動提交:void setAutoCommit(boolean autoCommit)測試
二、執行各個SQL語句,加入到批處理之中
三、若是全部語句執行成功,則提交事務 commit();若是出現了錯誤,則回滾:rollback()
核心代碼:
conn.setAutoCommit(false); // 取消自動提交 把SQL語句加入批處理 stmt.addBatch(…) () stmt.addBatch(…) //執行批處理操做 stmt.executeBatch(); conn.commit(); // 提交事務 //若是發生錯誤 conn.rollback();
代碼舉例:
首先在sql中建立一個空的數據庫,如今在java中,使用PreparedStatement插入數據並修改數據。正常狀況下,代碼應該這樣寫:
1 package com.vae.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 9 public class JDBCtest { 10 11 12 //數據庫鏈接地址 13 public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb"; 14 //用戶名 15 public final static String USERNAME = "root"; 16 //密碼 17 public final static String PASSWORD = "smyh"; 18 //驅動類 19 public final static String DRIVER = "com.mysql.jdbc.Driver"; 20 21 22 public static void main(String[] args) { 23 // TODO Auto-generated method stub 24 //insert(p); 25 //update(p); 26 //delete(3); 27 insertAndQuery(); 28 } 29 30 31 //方法:使用PreparedStatement插入數據、更新數據 32 public static void insertAndQuery(){ 33 Connection conn = null; 34 try { 35 Class.forName(DRIVER); 36 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); 37 String sql1 = "insert into user(name,pwd)values(?,?)"; 38 String sql2 = "update user set pwd=? where name=?"; 39 PreparedStatement ps = conn.prepareStatement(sql1); 40 ps.setString(1, "smyhvae"); 41 ps.setString(2, "007"); 42 ps.executeUpdate(); 43 44 ps = conn.prepareStatement(sql2); 45 ps.setString(1, "008"); 46 ps.setString(2, "smyh"); 47 ps.executeUpdate(); 48 49 ps.close(); 50 conn.close(); 51 52 } catch (ClassNotFoundException e) { 53 e.printStackTrace(); 54 } catch (SQLException e) { 55 e.printStackTrace(); 56 } 57 } 58 59 }
事務處理:
如今咱們把上面的插入操做和修改操做變成一個事務,就要增長一部分代碼了。修改上方的insertAndQuery()方法裏面的代碼:
1 //方法:使用PreparedStatement插入數據、更新數據 2 public static void insertAndQuery(){ 3 Connection conn = null; 4 try { 5 Class.forName(DRIVER); 6 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); 7 conn.setAutoCommit(false);//設置爲手動提交事務 8 String sql1 = "insert into user(name,pwd)values(?,?)"; 9 String sql2 = "update user set pwd=? where name=?"; 10 PreparedStatement ps = conn.prepareStatement(sql1); 11 ps.setString(1, "smyhvae"); 12 ps.setString(2, "007"); 13 ps.executeUpdate(); 14 15 ps = conn.prepareStatement(sql2); 16 ps.setString(1, "008"); 17 ps.setString(2, "smyh"); 18 ps.executeUpdate(); 19 conn.commit(); //若是全部sql語句成功,則提交事務 20 ps.close(); 21 conn.close(); 22 23 } catch (ClassNotFoundException e) { 24 e.printStackTrace(); 25 } catch (SQLException e) { 26 e.printStackTrace(); 27 try { 28 conn.rollback();//只要有一個sql語句出現錯誤,則將事務回滾 29 } catch (SQLException e1) { 30 e1.printStackTrace(); 31 } 32 } 33 34 }
核心代碼是第07行、19行、28行。這三行代碼就完成了事務處理的操做。兩個sql語句中,只要有一個語句出現錯誤,程序將沒法運行,說明事務提交失敗,且報錯以下:
2、封裝JDBC工具類
以前的JDBC代碼分析:
咱們能夠先回顧一下上一篇博文中的第五段:使用PreparedStatement重構增刪改查。
經過分析能夠發現有如下不足:有許多重複的代碼、每次都要加載驅動、獲取鏈接等。增刪改查無非只是slq語句不同而已。
封裝工具類就是一個抽象的過程,咱們能夠把如今代碼中很是公用的代碼抽取出來,造成一個工具類。
咱們先把以前的文章中,使用PreparedStatement查詢數據庫的代碼貼出來,方便和後面的內容進行對比,省的翻來翻去麻煩。
使用PreparedStatement查詢數據庫:(重構前)
在這以前,請建好一個Person類,參考上一篇博文就好了。而後,JDBCtest.java的代碼以下:
1 package com.vae.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 9 public class JDBCtest { 10 11 12 //數據庫鏈接地址 13 public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb"; 14 //用戶名 15 public final static String USERNAME = "root"; 16 //密碼 17 public final static String PASSWORD = "smyh"; 18 //驅動類 19 public final static String DRIVER = "com.mysql.jdbc.Driver"; 20 21 22 public static void main(String[] args) { 23 // TODO Auto-generated method stub 24 Person p = new Person(); 25 26 p = findById(2); 27 System.out.println(p); 28 } 29 30 31 32 // 使用PreparedStatement查詢數據 33 public static Person findById(int id){ 34 Person p = null; 35 try { 36 Class.forName(DRIVER); 37 Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); 38 String sql = "select name,age,description from person where id=?"; 39 PreparedStatement ps = conn.prepareStatement(sql); 40 //設置佔位符對應的值 41 ps.setInt(1, id); 42 43 ResultSet rs = ps.executeQuery(); 44 if(rs.next()){ 45 p = new Person(); 46 p.setId(id); 47 p.setName(rs.getString(1)); 48 p.setAge(rs.getInt(2)); 49 p.setDescription(rs.getString(3)); 50 51 } 52 rs.close(); 53 ps.close(); 54 conn.close(); 55 56 57 } catch (ClassNotFoundException e) { 58 e.printStackTrace(); 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 } 62 return p; 63 } 64 65 66 }
接下來開始真正的工做了,從零開始。
封裝工具類:
新建工程文件,結構以下:
(1)先新建一個DBUtils工具類:
1 package com.vae.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.Statement; 8 import java.util.ResourceBundle; 9 10 /** 11 * 數據庫操做工具類 12 * @author lamp 13 * 14 */ 15 public class DBUtils { 16 17 //數據庫鏈接地址 18 public static String URL; 19 //用戶名 20 public static String USERNAME; 21 //密碼 22 public static String PASSWORD; 23 //mysql的驅動類 24 public static String DRIVER; 25 26 private static ResourceBundle rb = ResourceBundle.getBundle("com.vae.jdbc.db-config"); 27 28 private DBUtils(){} 29 30 //使用靜態塊加載驅動程序 31 static{ 32 URL = rb.getString("jdbc.url"); 33 USERNAME = rb.getString("jdbc.username"); 34 PASSWORD = rb.getString("jdbc.password"); 35 DRIVER = rb.getString("jdbc.driver"); 36 try { 37 Class.forName(DRIVER); 38 } catch (ClassNotFoundException e) { 39 e.printStackTrace(); 40 } 41 } 42 //定義一個獲取數據庫鏈接的方法 43 public static Connection getConnection(){ 44 Connection conn = null; 45 try { 46 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); 47 } catch (SQLException e) { 48 e.printStackTrace(); 49 System.out.println("獲取鏈接失敗"); 50 } 51 return conn; 52 } 53 54 /** 55 * 關閉數據庫鏈接 56 * @param rs 57 * @param stat 58 * @param conn 59 */ 60 public static void close(ResultSet rs,Statement stat,Connection conn){ 61 try { 62 if(rs!=null)rs.close(); 63 if(stat!=null)stat.close(); 64 if(conn!=null)conn.close(); 65 } catch (SQLException e) { 66 e.printStackTrace(); 67 } 68 } 69 70 }
28行:既然是工具類,通常不要實例化,此時能夠採用單例設計模式,或者將構造方法私有化。
26行:很明顯能夠看到,咱們是將鏈接數據庫的URL、用戶名,密碼等信息編寫在一個屬性文件(jdbc.properties)中,稍後再來定義這個屬性文件。
31行:爲避免重複代碼,使用靜態代碼塊:只會在類加載的時候執行一次。
42行:定義一個獲取數據庫鏈接的方法
60行:關閉數據庫鏈接
(2)接下來新建一個屬性文件,new-->file,命名爲:db-config.properties,代碼以下:
jdbc.url=jdbc:mysql://localhost:3306/jdbcdb jdbc.username=root jdbc.password=smyh jdbc.driver=com.mysql.jdbc.Driver
之後若是須要修改配置信息,只須要在這裏改就好了。注意在上面的DBUtils類中是怎麼來調用這個配置信息的。
(3)緊接着新建文件,定義好Person類:
1 package com.vae.jdbc; 2 3 public class Person { 4 private int id; 5 private String name; 6 private int age; 7 private String description; 8 public int getId() { 9 return id; 10 } 11 public void setId(int id) { 12 this.id = id; 13 } 14 public String getName() { 15 return name; 16 } 17 public void setName(String name) { 18 this.name = name; 19 } 20 public int getAge() { 21 return age; 22 } 23 public void setAge(int age) { 24 this.age = age; 25 } 26 public String getDescription() { 27 return description; 28 } 29 public void setDescription(String description) { 30 this.description = description; 31 } 32 public Person(int id, String name, int age, String description) { 33 super(); 34 this.id = id; 35 this.name = name; 36 this.age = age; 37 this.description = description; 38 } 39 public Person(String name, int age, String description) { 40 super(); 41 this.name = name; 42 this.age = age; 43 this.description = description; 44 } 45 public Person() { 46 super(); 47 // TODO Auto-generated constructor stub 48 } 49 @Override 50 public String toString() { 51 return "Person [id=" + id + ", name=" + name + ", age=" + age 52 + ", description=" + description + "]"; 53 } 54 55 56 }
(4)而後開始編寫主程序來測試一下:
1 package com.vae.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 9 public class Test { 10 11 public static void main(String[] args) { 12 Person p = new Person(); 13 p = findById(1); 14 System.out.println(p); 15 } 16 17 18 19 20 /** 21 * 查詢的方法 22 */ 23 public static Person findById(int id){ 24 Person p =null; 25 //經過工具類獲取數據庫鏈接 26 Connection conn = DBUtils.getConnection(); 27 PreparedStatement ps = null; 28 ResultSet rs = null; 29 String sql = "select name,age,description from person where id=?"; 30 try { 31 ps = conn.prepareStatement(sql); 32 //設置佔位符對應的值 33 ps.setInt(1, id); 34 rs = ps.executeQuery(); 35 if(rs.next()){ 36 p = new Person(); 37 p.setName(rs.getString(1)); 38 p.setAge(rs.getInt(2)); 39 p.setDescription(rs.getString(3)); 40 } 41 } catch (SQLException e) { 42 e.printStackTrace(); 43 }finally{ 44 //經過工具類關閉數據庫鏈接 45 DBUtils.close(rs, ps, conn); 46 } 47 return p; 48 49 } 50 51 }
測試程序是能夠運行的。這樣,咱們的工具類就建好了。