所谓事务是指:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
事务的ACID属性
原子性,Atomicity:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性,Consistency:事务必须使数据库从一个一致性状态变换到另一个一致性状态。
隔离性,Isolation:一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性,Durability:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
为了让多个SQL语句作为一个事务执行:
- 调用Connection对象的setAutoCommit(false);以取消自动提交事务
- 在所有SQL语句都执行后,调用commit();方法提交事务
- 在出现异常时,调用rollback()方法回滚事务
- 若此时Connection没有被关闭,则需要恢复其自动提交状态
关于事务:
如果多个操作,每个操作使用的是自己的单独的连接,则无法保证事务。
具体步骤:
事务操作开始前,开始事务:取消Connection默认的提交行为;
如果事务的操作都成功,则提交事务;
回滚事务:若出现异常,则在catch块中回滚事务。
代码:
-
新增DAO一个方法,这个方法把Connection提出来作为传参
// 外部来处理Connection void update(Connection conn, String sql, Object... args) { PreparedStatement ps = null; try { ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, null); } }
测试事务
package com.litian.jdbc; import java.sql.Connection; import java.sql.SQLException; /** * @author: Li Tian * @contact: litian_cup@163.com * @software: IntelliJ IDEA * @file: TransactionTest.java * @time: 2020/4/1 14:06 * @desc: | */ public class TransactionTest { public static void main(String[] args) { DAO dao = new DAO(); Connection conn = null; try { conn = JDBCTools.getConnection(); // 开始事务:取消默认提交 conn.setAutoCommit(false); String sql = "update t_user2 set money = money - 500 where id = 21023"; dao.update(conn, sql); // 插入错误 int i = 10 / 0; System.out.println(i); sql = "update t_user2 set money = money + 500 where id = 21024"; dao.update(conn, sql); // 提交事务 conn.commit(); } catch (Exception e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } finally { JDBCTools.release(null, null, conn); } } }
事务的隔离级别
脏读:读取了更新还未提交的数据,但进行了回滚,所以读取的内容是临时的且无效的。
不可重复读:某个事务多次读取一个字段,值却不同,这是因为中间别的事务更新的该字段。
幻读:某个事务从一个表中读取了信息,然后另一个事务更新了该表,使得之前事务再读的时候,表的行数改变了。
数据库提供了4种事务隔离级别
- READ UNCOMMITED:读未提交数据,3种问题都会出现
- READ COMMITED:读已提交数据,避免脏读
- REPEATABLE READ:可重复度,避免脏读和不可重复读
- SERIALIZABLE:串行化,避免3种问题
Oracle支持2种事务隔离级别:READ COMMITED(默认)和SERIALIZABLE
Mysql支持4种事务隔离级别:默认REPEATABLE READ
在JDBC程序中可以通过Connection的setTransactionIsolation来设置事务的隔离级别