事务
回顾:ACID原则
原子性:要么全部完成,要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库
隔离性问题:
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变
虚读(幻读):在同一个事务内,读取到了别人插入的数据,导致前后读出来结果不一致
模拟转账事务
已知表格
测试事务成功
package com.database.lesson04;
import com.database.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
//创建连接
conn = JdbcUtils.getConnection();
//关闭数据库的自动提交功能 == 自动会开启事务
conn.setAutoCommit(false);
String sql1 = "update account set money=money-100 where name='A'";
pst = conn.prepareStatement(sql1);
int i = pst.executeUpdate();
if(i > 0){
System.out.println("发起转账!");
}
String sql2 = "update account set money=money+100 where name='B'";
pst = conn.prepareStatement(sql2);
int j = pst.executeUpdate();
if(j > 0){
System.out.println("接受转账!");
}
//业务完毕,提交事务
conn.commit();
System.out.println("转账成功!");
} catch (SQLException throwables) {
try {
//如果转账失败,那么让事务回滚
conn.rollback();//捕获一下异常
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}finally {
JdbcUtils.release(conn,pst,null);
}
}
}
模拟事务失败
在“发起转账”后使代码停止运行,未进行“接受转账”
结果为发生变化,说明事务回滚了(默认自动回滚了,没有执行到回滚代码)