1. 程式人生 > >JDBC例子4_事務管理

JDBC例子4_事務管理

事務管理

1 事務概述
 事務指的是邏輯上的一組操作(多條sql語句),組成這組操作的各個單元要麼全都成功,要麼全都失敗.
 事務作用:保證在一個事務中多次操作要麼全都成功,要麼全都失敗.

例如轉賬:

update account set money=money-100 where name='tom';//tom轉出100塊
update account set money=money+100 where name='jerry';//jerry收到100塊

以上兩條sql語句,很明顯是一組語句,因為轉賬要麼都成功要麼都失敗,不應該出現一方成功另一方失敗的情況.那麼我們就需要把他們看成一個事務.

事務處理

事務處理:保證所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit),要麼整個事務回滾(rollback)到最初狀態
當一個連線物件被建立時,預設情況下是自動提交事務:每次執行一個 SQL 語句時,如果執行成功,就會向資料庫自動提交,而不能回滾。

事務開始於:
• 連線到資料庫上,並執行一條DML語句(INSERT、UPDATE或DELETE)。
• 前一個事務結束後,又輸入了另外一條DML語句。
事務結束於:
• 執行COMMIT或ROLLBACK語句。
• 執行一條DDL語句,例如CREATE TABLE語句;在這種情況下,會自動執行COMMIT語句。
• 執行一條DCL語句,例如GRANT語句;在這種情況下,會自動執行COMMIT語句。
• 斷開與資料庫的連線。
• 執行了一條DML語句,該語句卻失敗了;在這種情況中,會為這個無效的DML語句執行ROLLBACK語句。

事務特性
原子性:強調事務的不可分割.多條語句要麼都成功,要麼都失敗。
一致性:強調的是事務的執行的前後,資料要保持一致.
隔離性:一個事務的執行不應該受到其他事務的干擾.
永續性:事務一旦結束(提交/回滾)資料就持久保持到了資料庫.

2 使用JDBC原生的API進行事務管理

為了讓多個 SQL 語句作為一個事務執行:
呼叫 Connection 物件的 setAutoCommit(false); 以取消自動提交事務
在所有的 SQL 語句都成功執行後,呼叫 commit(); 方法提交事務
在出現異常時,呼叫 rollback(); 方法回滾事務
若此時 Connection 沒有被關閉, 則需要恢復其自動提交狀態

#建立賬號表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);

package cn.njit.aff;
/****
 * 使用jdbc實現事務
 * 
 */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Testjdbc {

	public static void main(String[] args) {
		Connection conn=getConnection();
		try {
			conn.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}//設定成不自動提交
		
		String sql="Update account set money=money-? where name=?";
		PreparedStatement psmt;
	
		try {
			psmt=conn.prepareStatement(sql);
			psmt.setDouble(1, 500);
			psmt.setString(2, "螺紋");
			psmt.executeUpdate();
			System.out.println("----");
			//-------------------
			int x=1/0;
			//製造異常,引起回滾
			//-------------------
			
			sql="update account set money=money+? where name=?";
			psmt=conn.prepareStatement(sql);
			psmt.setDouble(1, 500);
			psmt.setString(2, "劉智偉");
			psmt.executeUpdate();
			System.out.println("----");
			
			conn.commit();

		} catch (SQLException e) {			
			try {
				System.out.println("======");
				e.printStackTrace();
				conn.rollback();
			}catch(SQLException e1) {
				e1.printStackTrace();
			}
		}finally {
			if(null!=conn) {
				try{
					conn.close();
				}catch (SQLException e2){
					e2.printStackTrace();
				}
			}
		}
	}
	
	public static Connection getConnection() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		String url="jdbc:mysql://localhost:3306/njit?useUnicode=true&characterEncoding=utf-8";
		String name="root";
		String password="admin";
		Connection conn = null;
		
		try {
			conn=DriverManager.getConnection(url, name, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		
		return conn;
		
	}
}

3 使用DBUtils實現事務管理

要點:

QueryRunner qr = new QueryRunner();//為了支援事務,不能傳遞連線池
conn = C3P0Utils02.getConnection(); //獲取jdbc原生連線
conn.setAutoCommit(false); //開啟事務
conn.commit(); //正常,則提交事務
conn.rollback(); //異常或者業務不正確,則回滾
Conn.close(); //最後關閉事務


package cn.njit.aff;
/****
 * 使用DBUtils實現事務
 */
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import util.C3P0Utils;

public class TestDBUtils {

	public static void main(String[] args) {
		testUpdate();
	}

	static void testUpdate() {
		QueryRunner qr = new QueryRunner();
		// 不能直接把conn放進去
		Connection conn = null;
		try {
			conn = C3P0Utils.getConnection();
			System.out.println("0");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			conn.setAutoCommit(false);
			String sql = "Update account set money=money-? where name=?";
			Object[] o = { 500, "劉智偉" };
			qr.update(conn, sql, o);
			System.out.println("1");
			// ---------------
			int x=1/0;
			// ---------------
			String str = "update account set money=money+? where name=?";
			Object[] o2 = { 500, "螺紋" };
			qr.update(conn, str, o2);
			System.out.println("2");
			
			conn.commit();
		} catch (SQLException e) {
			try {
				System.out.println("===========");
				conn.rollback();
				e.printStackTrace();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			try {
				if (null != conn) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

	}

}