事務(wù)
基本概念:
事務(wù)使指一組最小邏輯操作單元开镣,里面有多個操作組成
組成事務(wù)的每一部分必須要同時提交成功,
如果有一個操作失敗咽扇,整個操作就回滾
事務(wù)的 ACID特性:
- 原子性(Atomicity)
原子性是指事務(wù)是一個不可分割的工作單位糠馆,
事務(wù)中的操作要么都發(fā)生耽装,要么都不發(fā)生- 一致性(Consistency)
事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另外一個一致性狀態(tài)- 隔離性(Isolation)
事務(wù)的隔離性是多個用戶、并發(fā)訪問數(shù)據(jù)庫時,
數(shù)據(jù)庫為每一個用戶開啟的事務(wù),
不能被其他事務(wù)的操作數(shù)據(jù)所干擾谍婉,
多個并發(fā)事務(wù)之間要相互隔離- 持久性(Durability)
持久性是指一個事務(wù)一旦被提交,
它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的镀钓,
接下來即使數(shù)據(jù)庫發(fā)生故障也不應該對其有任何影響
默認情況下穗熬,Connection 對象處于自動提交模式下,
這意味著它在執(zhí)行每個語句后都會自動提交更改
如果禁用了自動提交模式丁溅,那么要提交更改就必須顯式調(diào)用 commit 方法唤蔗;否則無法保存數(shù)據(jù)庫更改
void setAutoCommit(boolean autoCommit) throws SQLException
將此連接的自動提交模式設(shè)置為給定狀態(tài)。
如果連接處于自動提交模式下窟赏,則它的所有 SQL 語句將被執(zhí)行并作為單個事務(wù)提交
否則妓柜,它的 SQL 語句將聚集到事務(wù)中,
直到調(diào)用 commit 方法或 rollback 方法為止饰序。
默認情況下领虹,新連接處于自動提交模式
那么,本人現(xiàn)在來展示下事務(wù)的使用:
例子:
這天求豫,一個粉絲想要資助右轉(zhuǎn)哥(做夢ing)塌衰,粉絲和右轉(zhuǎn)哥的銀行賬戶金額分別為2333和10999诉稍,而粉絲要給右轉(zhuǎn)哥轉(zhuǎn)賬4333,以便給右轉(zhuǎn)哥湊個6666出來
轉(zhuǎn)帳前 展示
那么最疆,請看如下代碼:
package edu.youzg.about_jdbc.core;
import edu.youzg.about_jdbc.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class FundDemo {
public static void main(String[] args) throws Exception {
//轉(zhuǎn)賬
//默認事務(wù)是自動開啟的
Connection conn1 = JDBCUtils.getConnection();
//編寫sql語句
String sql1="update bank set money=money-4333 where username='fan'";
String sql2 = "update bank set money=money+4333 where username='youzg'";
//獲取操作對象
PreparedStatement statement1 = conn1.prepareStatement(sql1);
PreparedStatement statement2 = conn1.prepareStatement(sql2);
//執(zhí)行:
statement1.executeUpdate(); //單獨事務(wù)1 自動提交
//模擬一個異常
System.out.println(1/0);
statement2.executeUpdate();//單獨的事務(wù)2 自動提交
//釋放資源
conn1.close();
statement1.close();
statement2.close();
}
}
那么杯巨,本人來展示下運行后的結(jié)果:
可以看到:當轉(zhuǎn)賬過程中出現(xiàn)了異常之后,發(fā)生異常的那句代碼之后的代碼段都不會執(zhí)行
所以導致了努酸,粉絲已經(jīng)轉(zhuǎn)賬過了服爷,但是右轉(zhuǎn)哥這里卻沒有收到轉(zhuǎn)賬
這跟本人之前講解的異常的知識點有關(guān):
異常相當于return
那么,上面的結(jié)果顯然是不合理的获诈,
轉(zhuǎn)賬不能因為一個異常導致轉(zhuǎn)的金額就憑空消失了
所以仍源,這里就運用到了事務(wù)性質(zhì)
那么,本人現(xiàn)在來展示下使用事務(wù)的性質(zhì)來解決上述問題的代碼:
package edu.youzg.about_jdbc.core;
import edu.youzg.about_jdbc.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class FundDemo {
public static void main(String[] args) throws Exception {
Connection conn1=null;
try {
//轉(zhuǎn)賬
//默認事務(wù)是自動開啟的
conn1 = JDBCUtils.getConnection();
//設(shè)置數(shù)據(jù)庫的隔離級別舔涎,一般不要設(shè)置笼踩。數(shù)據(jù)庫裝好之后的默認級別就OK
//1.把事務(wù)改成手動提交。
conn1.setAutoCommit(false);
//編寫sql語句
String sql1 = "update bank set money=money-4333 where username='fan'";
String sql2 = "update bank set money=money+4333 where username='youzg'";
//獲取操作對象
PreparedStatement statement1 = conn1.prepareStatement(sql1);
PreparedStatement statement2 = conn1.prepareStatement(sql2);
//執(zhí)行:
statement1.executeUpdate();
//模擬異常
System.out.println(1 / 0);
statement2.executeUpdate();
} catch (Exception e) {
try {
//一旦遇到異常亡嫌,咱們就回滾事務(wù)
conn1.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//不管有沒有遇到異常,我們都提交事務(wù)
try {
conn1.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("操作完成");
}
}
那么嚎于,我們再來運行下代碼,來看看運行后的結(jié)果:
那么挟冠,可以看到:
即使發(fā)生了異常于购,也不會導致總金額減少,保證了數(shù)據(jù)的一致性
那么知染,現(xiàn)在肋僧,本人來講解下 事務(wù)的隔離級別:
事務(wù)的隔離級別:
若是我們不考慮事務(wù)的隔離性,就會產(chǎn)生如下三種讀問題:
- 臟讀:
在一個事務(wù)中讀取到另一個事務(wù) 沒有提交的數(shù)據(jù)- 不可重復讀:
在一個事務(wù)中持舆,兩次查詢的結(jié)果不一致(針對的update操作)
即 在數(shù)據(jù)庫訪問中色瘩,一個事務(wù)范圍內(nèi)兩個相同的查詢卻返回了不同數(shù)據(jù)- 虛讀(幻讀):
在一個事務(wù)中,兩次查詢的結(jié)果不一致(針對的insert操作) 無法演示出來
(MySQL已經(jīng)默認避免了)
那么逸寓,現(xiàn)在居兆,本人來講解下事務(wù)的隔離級別:
隔離級別:
- read uncommitted:
讀未提交
上面的三個問題都會出現(xiàn)- read committed:
讀已提交
可以避免臟讀的發(fā)生
(Oracle 默認級別)- repeatable read:
可重復讀
可以避免臟讀和不可重復讀的發(fā)生
(MySQL 默認級別)- serializable:
串行化
可以避免所有的問題
相關(guān)語句和方法:
- sql語句:
- set session transaction isolation level 隔離級別:
將 隔離級別 設(shè)置為 指定級別- select @@tx_isolation:
查看數(shù)據(jù)庫的隔離級別
- Java方法
- void setTransactionIsolation(int level):
控制隔離級別
那么,本篇博文的知識點在這里就講解完畢了竹伸。
(請觀看本人博文 —— 《JDBC 專欄總集篇》)