一、事務(wù)概述
什么是事務(wù)
一件事情有n個(gè)組成單元,要不這n個(gè)組成單元同時(shí)成功、要不n個(gè)單元就同時(shí)失敗;就是將n個(gè)組成單元放到一個(gè)事務(wù)中。mysql的事務(wù)
默認(rèn)的事務(wù):一條sql語(yǔ)句就是一個(gè)事務(wù),默認(rèn)就開(kāi)啟事務(wù)并提交事務(wù)。
手動(dòng)事務(wù):
1)顯示的開(kāi)啟一個(gè)事務(wù):start transaction
2)事務(wù)提交:commit代表從開(kāi)啟事務(wù)到事務(wù)提交。中間所有的 sql 都認(rèn)為有效、真正的更新數(shù)據(jù)庫(kù)。
3)事務(wù)的回滾:rollback代表事務(wù)的回滾。從開(kāi)啟事務(wù)到事務(wù)回滾,中間的所有的 sql 操作都認(rèn)為無(wú)效、數(shù)據(jù)庫(kù)沒(méi)有被更新。
二、JDBC事務(wù)操作
默認(rèn)是自動(dòng)事務(wù):
執(zhí)行 sql 語(yǔ)句:executeUpdate() ----> 每執(zhí)行一次 executeUpdate 方法代表事務(wù)自動(dòng)提交
通過(guò) jdbc 的 API 手動(dòng)事務(wù):
開(kāi)啟事務(wù):conn.setAutoComnmit(false);
提交事務(wù):conn.commit();
回滾事務(wù):conn.rollback();
注意:控制事務(wù)的 connnection 必須是同一個(gè),即執(zhí)行 sql 的 connection 與開(kāi)啟事務(wù)的 connnection 必須是同一個(gè)才能對(duì)事務(wù)進(jìn)行控制。
public static void main(String[] args) {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
//runner.update("update account set money=15000 where name='tom'");
//獲得一個(gè)Connection
conn = DataSourceUtils.getConnection();
//開(kāi)啟事務(wù)
conn.setAutoCommit(false);
runner.update(conn, "update account set money=15000 where name='tom'");
//提交或回滾事務(wù)
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
三、DBUtils事務(wù)操作
- QueryRunner
1)有參構(gòu)造:QueryRunner runner = new QueryRunner(DataSource dataSource);
有參構(gòu)造將數(shù)據(jù)源(連接池)作為參數(shù)傳入QueryRunner,QueryRunner會(huì)從連接池中獲得一個(gè)數(shù)據(jù)庫(kù)連接資源操作數(shù)據(jù)庫(kù),所以直接使用無(wú) Connection 參數(shù)的 update 方法即可操作數(shù)據(jù)庫(kù)
2)無(wú)參構(gòu)造:QueryRunner runner = new QueryRunner();
無(wú)參的構(gòu)造沒(méi)有將數(shù)據(jù)源(連接池)作為參數(shù)傳入 QueryRunner ,那么我們?cè)谑褂?QueryRunner 對(duì)象操作數(shù)據(jù)庫(kù)時(shí)要使用有 Connection 參數(shù)的方法
四、使用ThreadLocal綁定連接資源

import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class MyDataSourceUtils {
//獲得Connection ----- 從連接池中獲取
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
//創(chuàng)建ThreadLocal
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//開(kāi)啟事務(wù)
public static void startTransaction() throws SQLException{
Connection conn = getCurrentConnection();
conn.setAutoCommit(false);
}
//獲得當(dāng)前線程上綁定的conn
public static Connection getCurrentConnection() throws SQLException{
//從ThreadLocal尋找 當(dāng)前線程是否有對(duì)應(yīng)Connection
Connection conn = tl.get();
if(conn==null){
//獲得新的connection
conn = getConnection();
//將conn資源綁定到ThreadLocal(map)上
tl.set(conn);
}
return conn;
}
public static Connection getConnection() throws SQLException{
return dataSource.getConnection();
}
//回滾事務(wù)
public static void rollback() throws SQLException {
getCurrentConnection().rollback();
}
//提交事務(wù)
public static void commit() throws SQLException {
Connection conn = getCurrentConnection();
conn.commit();
//將Connection從ThreadLocal中移除
tl.remove();
conn.close();
}
}
五、事務(wù)的特性和隔離級(jí)別(概念性問(wèn)題---面試)
事務(wù)的特性ACID
1)原子性(Atomicity)原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
2)一致性(Consistency)一個(gè)事務(wù)中,事務(wù)前后數(shù)據(jù)的完整性必須保持一致。
3)隔離性(Isolation)多個(gè)事務(wù),事務(wù)的隔離性是指多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí), 一個(gè)用戶的事務(wù)不能被其它用戶的事務(wù)所干擾,多個(gè)并發(fā)事務(wù)之間數(shù)據(jù)要相互隔離。
4)持久性(Durability)持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來(lái)即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。并發(fā)訪問(wèn)問(wèn)題----由隔離性引起
如果不考慮隔離性,事務(wù)存在3種并發(fā)訪問(wèn)問(wèn)題。
1)臟讀:B事務(wù)讀取到了A事務(wù)尚未提交的數(shù)據(jù) ------ 要求B事務(wù)要讀取A事務(wù)提交的數(shù)據(jù)
2)不可重復(fù)讀:一個(gè)事務(wù)中 兩次讀取的數(shù)據(jù)的內(nèi)容不一致 ----- 要求的是一個(gè)事務(wù)中多次讀取時(shí)數(shù)據(jù)是一致的 --- unpdate
3)幻讀/虛讀:一個(gè)事務(wù)中 兩次讀取的數(shù)據(jù)的數(shù)量不一致 ----- 要求在一個(gè)事務(wù)多次讀取的數(shù)據(jù)的數(shù)量是一致的 --insert delete事務(wù)的隔離級(jí)別
1)read uncommitted : 讀取尚未提交的數(shù)據(jù) :哪個(gè)問(wèn)題都不能解決 ---- 1
2)read committed:讀取已經(jīng)提交的數(shù)據(jù) :可以解決臟讀 ---- oracle默認(rèn)的 ---- 2
3)repeatable read:重復(fù)讀取:可以解決臟讀 和 不可重復(fù)讀 --- mysql默認(rèn)的 ---- 4
4)serializable:串行化:可以解決 臟讀 不可重復(fù)讀 和 虛讀--- 相當(dāng)于鎖表 ---- 8
注意:mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
查看mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別:select @@tx_isolation
設(shè)置mysql的隔離級(jí)別:set session transaction isolation level 設(shè)置事務(wù)隔離級(jí)別

