1.事务概述
一件事情有n多个组成单元,n个单元全部正确是才都成功,一个错误就都失败。
栗子:转账操作,有a转出和b转入两个步骤分别对应着一条转出sql语句和一条转入sql语句,当执行完转出sql语句后转入sql语句出异常了,这时如果没有事务那么a就会白白损失钱,b也没有收到,有事务时必须两条sql语句同时成功才会提交数据。
1.2)mysql的事务
mysql是默认事务:一条sql语句就是一个事务,执行完sql以后直接提交(执行update)
a.开启事务:start transaction
b.提交事务:commit(从开启事务到执行提交之间的所有sql都提交)
c.回滚事务:rollback(从开事务到执行回滚之间的所有sql都取消)
2.jdbc事务操作
默认事务提交:执行sql语句executeUpdate(),后自动提交
a.开启事务:conn.setAutoComnmit(false);
b.提交事务:conn.commit();
c.回滚事务:conn.rollback();
注意:执行事务操作的conn必须是同一个才能对事务进行有效的操作
3.DbUtil事务操作(ThreadLocal)(划重点)
转账操作时所有的方法调用都是一个线程(一个service方法调用多个dao方法),下面方法也是基于jdbc事务的
在DataSourceUtil中封装开启事务、提交事务、回滚事务的三个方法,用ThreadLocal(线程)来明确是同一个conn
QueryRunner类是有无conn参数和有conn参数两个构造方法,之前我们使用无conn的,事务使用有conn的(同一个conn)
public class DataSourceUtil {
/**
* 事务处理ThreadLocal方法,使用时直接在service调用三个方法
* 开启事务在sql语句执行前,提交事务在finally中执行,回滚事务在catch中执行
*/
//获得Connection ----从连接池中获取
private static ComboPooledDataSource mydataSource = new ComboPooledDataSource("imwj");
//创建ThreadLocal
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//获取当前线程上绑定的conn
public static Connection getCurrentConnection() throws SQLException{
//从ThreadLocal线程中寻找 当前线程是否有对应的Connection
Connection conn = tl.get();
if(conn==null){
//获取一个新的线程
conn = getConnection();
//将conn资源放入ThreadLocal中
tl.set(conn);
}
return conn;
}
//开启事务方法
public static void starTransaction() throws SQLException{
Connection conn = getCurrentConnection();
conn.setAutoCommit(false);
}
//提交事务方法
public static void commit() throws SQLException{
Connection conn = getCurrentConnection();
conn.commit();
//将Connection从当前线程(ThreadLocal)移除
tl.remove();
conn.close();
}
//回滚事务方法
public static void rollback() throws SQLException{
getCurrentConnection().rollback();
}
}
4.事务的特性
原子性:指事务是一个不可分割的工作单位,事务中的操作 要么都发生,要么都不发生。
隔离性:一个事务中,事务前后数据的完整性必须保持一致。
一致性:多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性:多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
总结:
mysql的事务控制:
开启事务:start transaction;
提交:commit;
回滚:rollback;
JDBC事务控制:
开启事务:conn.setAutoCommit(false);
提交:conn.commit();
回滚:conn.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