首先需要回顧一下上一篇文章中的內容:MySQL數據庫學習筆記(九)----JDBC的PreparedStatement接口重構增刪改查
一、JDBC事務處理:
我們已經知道,事務的概念即:所有的操作要麼同時成功,要麼同時失敗。在MySQL中提供了Commit、Rollback命令進行事務的提交與回滾。實際上在JDBC中也存在事務處理,如果要想進行事務處理的話,則必須按照以下的步驟完成。
JDBC中事務處理的步驟:
1、要取消掉JDBC的自動提交:void setAutoCommit(boolean autoCommit)
2、執行各個SQL語句,加入到批處理之中
3、如果所有語句執行成功,則提交事務 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語句中,只要有一個語句出現錯誤,程序將無法運行,說明事務提交失敗,且報錯如下:

二、封裝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 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類:

(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 }
測試程序是可以運行的。這樣,我們的工具類就建好了。
package tool;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;public class JdbcXmlParse { /** 數據庫配置信息 */ private static HashMap<String, JdbcBean> beanMap; public static JdbcBean getJdbcBean(String dbName) { if (beanMap == null) { // 配置文件路徑 String path = System.getProperty("user.dir") + File.separator + "src/tool/dbConfig.xml"; try { new JdbcXmlParse().initDbconfig(path); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return beanMap.get(dbName); } private void initDbconfig(String dbCfgPath) throws ParserConfigurationException, SAXException, IOException { // 初始化map beanMap = new HashMap<String, JdbcBean>(); DocumentBuilder dombuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); InputStream is = new FileInputStream(dbCfgPath); Element root = dombuilder.parse(is).getDocumentElement(); NodeList childs = root.getChildNodes(); for (int i = 0; i < childs.getLength(); i++) { Node child = childs.item(i); if ("db".equals(child.getNodeName())) { // 數據庫種類 String dbType......余下全文>>
你找對了Jar包沒有呢?