【事務概述】
1.什麼是事務?
邏輯上的一組操作,組成這組操作的各個單元要麼全部成功,要麼全部失敗。
2.mysql事務
默認的事務:一條sql語句就是一個事務,默認就開啓事務並提交事務。
手動事務:(1) 顯示的開啓一個事務 -- start transaction
(2) 事務提交 -- commit 代表從開啓事務到提交事務 中間所有的sql語句都認爲有效,真正的更新數據庫。
(3) 事務的回滾 -- rollback 從開啓事務到回滾事務 中間所有sql操作都認爲無效,數據庫沒更新。
【JDBC事務操作】
(1). 默認是自動事務 執行sql語句:executeUpdate(),每執行一次executeUpdate()方法代表事務自動提交。
(2). 手動事務 開啓事務:con.setAutoCommit(false); 提交事務:con.commit(); 回滾事務:con.rollback();
注意:控制事務的connextion必須是同一個。
【DBUtils事務操作】
(1) 有參構造:QueryRunner runner = new QueryRunner(DataSource dataSource) 將數據源(連接池)作爲參數傳入QueryRunner,QueryRunner會從連接池中獲得一個數據庫連接資源操作數據庫,所以可以直接使用無Connection參數的update方法即可操作數據庫。
(2) 無參構造:QueryRunner runner = new QueryRunner() 沒有將數據源作爲參數傳入QueryRunner,操作數據庫的時候,要使用有Connection參數的方法。
【ThreadLocal工具類】-- 在一個線程中共享數據
ThreadLocal工具類底層就是一個Map,key存放的當前線程,value存放共享的數據。
ThreadLocal操作: set(value) get() remove()
c3p0-config.xml 數據庫配置文件
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///mybase1</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="namedConfig">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///mybase1</property>
<property name="user">root</property>
<property name="password">123</property>
</named-config>
</c3p0-config>
【ThreadLocal 在當前線程中存儲Connection】
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Utils {
// 使用默認配置信息 -- 自動讀取c3p0-config.xml中的配置信息
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 創建ThreadLocal -- 用於在當前線程中共享數據
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
// 靜態方法獲得連接池
public static DataSource getDataSource() {
return dataSource;
}
// 靜態方法獲得連接池
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 開啓事務
public static void startTransaction() throws SQLException {
Connection con = getCurrentConnection();
con.setAutoCommit(false);
}
// 回滾事務
public static void rollback() throws SQLException {
getCurrentConnection().rollback();
}
// 提交事務
public static void commit() throws SQLException {
Connection con = getCurrentConnection();
con.commit();
// 將Connection從ThreadLocal中刪除
tl.remove();
con.close();
}
// 獲得當前線程綁定的Connection
public static Connection getCurrentConnection() throws SQLException {
// 從ThreadLocal尋找,當前線程是否有對應的Connection
Connection con = tl.get();
if(con == null) {
// 獲得新的Connecton資源
con = getConnection();
// 將Connection資源綁定到ThreadLocal
tl.set(con);
}
return con;
}
}
【事務的特性】
(1)原子性(Automicity) 原子性是指事務一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
(2)一致性(Consistency) 事務前後數據的完整性必須保持一致。
(3)隔離性(Isolation) 多個用戶併發訪問數據庫時,一個用戶的事物不能被其他用戶的事物所幹擾,多個併發事物之間數據要隔離。
(4)持久性(Durability)一個事務一旦被提交,它對數據庫中數據的改變是持久性的,接下來即使數據庫發生故障也不應該對其有任何影響。
【併發訪問問題】--- 由隔離性引起
(1)髒讀:B事務讀到了A事務未提交的數據。--- 要求B事務要讀取A事務提交的數據。
(2)不可重複讀:一個事務中 兩次讀取到數據內容不一致 --- 要求的是一個事務中多次讀取到的數據是一致的。
(3)虛讀/幻讀: 一個事務中 兩次讀取的數據的數量不一致 --- 要求在一個事務多次的數據的數量是一致的。
【解決併發問題】--- 設置隔離級別
(1)read uncommitted: 讀取尚未提交的數據:哪個問題都不能解決。
(2)read committed: 讀取已經提交的數據:可以解決髒讀。--- oracle 默認的。
(3)repeatable read : 重讀讀取:可以解決髒讀 和 不可重複讀。--- mysql 默認的。
(4)serializable:串行化:可以解決髒讀,不可重複讀 和 虛讀。--- 相當於鎖表。
查看mysql數據庫默認的隔離級別:select @@tx_isolation
設置事務的隔離級別:set session transaction isolation level 事務隔離級別。
【總結】
mysql的事務控制:
開啓事務:start transaction
提交事務:commit
回滾:rollback
JDBC 事務控制
開啓事務:con.setAutocommit(false)
提交事務:con.commit()
回滾:con.rollback()
DBUtils的事務控制 也是通過jdbc控制
ThreadLocal:實現的是通過線程綁定的方式傳遞參數
概念:
事務的特性:ACID
併發問題:髒讀、不可重讀、幻讀
解決併發問題:設置隔離級別
read uncommitted
read committed
repeatable read(mysql默認)
serialazable
隔離級別的性能:
read uncommitted>read committed>repeatable read>serialazable
安全性:
read uncommitted<read committed<repeatable read<serialazable