JDBC操作事务
要么都成功,要么都失败
ACID原则:原子性、一致性、隔离性、持久性
原子性:要么全部完成,要么都不完成
一致性:结果总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库了
隔离性的问题:
脏读: 一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致
简单模拟转账,体验事务的要么都成功要么都失败
- 关闭数据库的自动提交功能,自动开启事务
- 执行一组事务
- 事务完毕,提交事务
当执行不成功时,在catch语句中自动回滚,相当于没有执行,数据库不进行改变
创建表格
/*创建账户表*/
CREATE TABLE account(
id INT primary key auto_increment,
NAME varchar(40),
money float
);
/*插入测试数据*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('C',1000);
模拟转账代码
package JDBC.TestTransaction;
import JDBC.statement.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction01 {
public static void main(String[] args) {
Connection con=null;
PreparedStatement st=null;
ResultSet rs=null;
try {
con=JdbcUtils.getConnection();
//关闭数据库的自动提交功能,自动开启事务
con.setAutoCommit(false);
//执行一组事务
String sql1="update account set money=money-100 where name='A'";
st=con.prepareStatement(sql1);
st.executeUpdate();
String sql2="update account set money=money+100 where name='B'";
st=con.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
con.commit();
System.out.println("转账成功!");
} catch (SQLException e) {
try {
//如果失败,就回滚事务
con.rollback();
//e.printStackTrace();这个语句其实已经默认回滚了
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} finally {
JdbcUtils.release(con,st,null);
}
}
}
转账成功:
如果在事务部分中间加入错误代码,使程序出现错误
则会回滚,转账失败
//执行一组事务
String sql1="update account set money=money-100 where name='A'";
st=con.prepareStatement(sql1);
st.executeUpdate();
int x=1/0;//报错,结束程序
String sql2="update account set money=money+100 where name='B'";
st=con.prepareStatement(sql2);
st.executeUpdate();