1. 程式人生 > 其它 >資料庫的事務及實現CRUD功能

資料庫的事務及實現CRUD功能

技術標籤:JDBCjavamysqljdbc

一、概念

一組邏輯操作單元(一個或多個DML操作),使資料從一種狀態變換到另一種狀態。

二、事務的屬性(ACID)

1.原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2.一致性(Consistency)
事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態。
3.隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。

2.1 資料庫的併發問題

資料操作過程中可能出現的問題:(針對隔離性)

  • 髒讀
    對於兩個事務 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的欄位。之後, 若 T2 回滾, T1讀取的內容就是臨時且無效的。
  • 不可重複讀
    對於兩個事務T1, T2, T1 讀取了一個欄位, 然後 T2 更新了該欄位。之後, T1再次讀取同一個欄位, 值就不同了。
  • 幻讀
    對於兩個事務T1, T2, T1 從一個表中讀取了一個欄位, 然後 T2 在該表中插入了一些新的行。之後, 如果 T1 再次讀取同一個表, 就會多出幾行。

2.2 四種隔離級別

在這裡插入圖片描述

  • mysql預設REPEATABLE READ

二、事務處理原則

保證所事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit)

,那麼這些修改就永久地儲存下來;要麼資料庫管理系統將放棄所作的所有修改,整個事務回滾(rollback)到最初狀態

三、說明

1.資料一旦提交,就不可回滾
2.哪些操作會導致資料的自動提交?

  • DDL操作一旦執行,都會自動提交。
    set autocommit = false 對DDL操作失效
  • DML預設情況下,一旦執行,就會自動提交。
    我們可以通過set autocommit = false的方式取消DML操作的自動提交。
  • 預設在關閉連線時,會自動的提交資料

四、程式碼體現

1.獲取資料庫的連線

Connection conn = JDBCUtils.getConnection();== //方式1:手動獲取連線 方式2:資料庫連線池==

conn.setAutoCommit(false); //體現事務

2.如下的多個DML操作,作為一個事務出現:

操作1:需要使用通用的增刪改查操作
//通用的增刪改查操作如何實現?//方式1:手動使用PreparedStatement實現;//方式2:使用dbutils.jar中QueryRunner類
操作2:需要使用通用的增刪改查操作

操作3:需要使用通用的增刪改查操作

conn.commit();

3.如果出現異常

conn.rollback();

4.關閉資源

JDBCUtils.closeResource(…,…,…); //方式1:手動關閉資源 方式2:DbUtils類的關閉方法

     @Test
	public void testUpdateWithTx() {
		Connection conn = null;
		try {
			conn = JDBCUtils.getConnection();
			System.out.println(conn.getAutoCommit());//true
			//1.取消資料的自動提交
			conn.setAutoCommit(false);
			
			String sql1 = "update user_table set balance = balance - 100 where user = ?";
			update(conn,sql1, "AA");
			
			//模擬網路異常
			System.out.println(10 / 0);
			
			String sql2 = "update user_table set balance = balance + 100 where user = ?";
			update(conn,sql2, "BB");
			
			System.out.println("轉賬成功");
			
			//2.提交資料
			conn.commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			//3.回滾資料
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			//修改其為自動提交資料
			//主要針對於使用資料庫連線池的使用
			try {
				conn.setAutoCommit(true);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			JDBCUtils.closeResource(conn, null);
		}
		
	}