事务:
要么都成功,要么都失败
ACID原则
- 原子性:要么全部完成,要么都不完成
- 一致性:总数不变
- 隔离性:多个进程互不干扰 若隔离不成功,脏读,不可重读,幻读
- 持久性:一旦提交,持久化到数据库了
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内重复读取表中数据,表数据发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来结果不一致
成功的:
开启事务conn.setAutoCommit(false);
一组业务执行完毕,提交业务conn.commit();
可以在catch语句中显示的定义 回滚语句 ,但默认失败就会回滚
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 st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 关闭数据库的自动提交功能,自动会开启最后不用开启
conn.setAutoCommit(false); //开启事务
String sql1 = "update account set money = money-100 where name = 'A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update account set money = money+100 where name = 'B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("成功!");
} catch (SQLException e) {
try {
conn.rollback();//如果失败,则回滚事务
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
JdbcUtils.release(conn, st, rs);
}
}
}
结果:
成功!
失败的:我们在两条sql中插入int x = 1 / 0;那必然失败。
如果失败,则默认回滚不需要显示定义
import com.duan.demo02.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 st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 关闭数据库的自动提交功能,自动会开启最后不用开启
conn.setAutoCommit(false); //开启事务
String sql1 = "update account set money = money-100 where name = 'A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
int x = 1 / 0;// 报错
String sql2 = "update account set money = money+100 where name = 'B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("成功!");
} catch (SQLException e) {
//try {
// conn.rollback();//如果失败,则回滚事务
//} catch (SQLException e1) {
// e1.printStackTrace();
// }
//如果失败,则默认回滚不需要显示定义
e.printStackTrace();
} finally {
JdbcUtils.release(conn, st, rs);
}
}
}
结果:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.duan.demo04.TestTransaction.main(TestTransaction.java:24)
import com.duan.demo02.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 st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 关闭数据库的自动提交功能,自动会开启最后不用开启
conn.setAutoCommit(false); //开启事务
String sql1 = "update account set money = money-100 where name = 'A'";
st = conn.prepareStatement(sql1);
st.executeUpdate();
String sql2 = "update account set money = money+100 where name = 'B'";
st = conn.prepareStatement(sql2);
st.executeUpdate();
//业务完毕,提交事务
conn.commit();
System.out.println("成功!");
} catch (SQLException e) {
//try {
// conn.rollback();//如果失败,则回滚事务
//} catch (SQLException e1) {
// e1.printStackTrace();
// }
//如果失败,则默认回滚不需要显示定义
e.printStackTrace();
} finally {
JdbcUtils.release(conn, st, rs);
}
}
}
结果:
成功!