1. 事务
基本概念:
事务使指一组最小逻辑操作单元,里面有多个操作组成。 组成事务的每一部分必须要同时提交成功,如果有一个操作失败,整个操作就回滚。
事务ACID特性:
l 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
l 一致性(Consistency
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
l 隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
l 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
案例
需求: 张三给李四转账
设计: 账户表
技术:
|-- Connection
- void setAutoCommit(boolean autoCommit) ; 设置事务是否自动提交,如果设置为false,表示手动提交事务。
- void commit() (); 手动提交事务
- void rollback() ; 回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
- Savepoint setSavepoint(String name) :
savepoint
- 要回滚到的Savepoint
对象
1:sql代码,账目表:
1 CREATE TABLE transfer( 2 id INT PRIMARY KEY AUTO_INCREMENT , 3 accName VARCHAR(20), 4 accmoney DOUBLE 5 )
2:设定事务,若事务中有语句出现错误,则回滚到事务的初始化
1 /** 2 * 这是个事务的操作类 3 * 4 * @author LZL 5 * 6 */ 7 public class Connection_false { 8 9 // 设定全局变量 10 private static Connection conn; 11 private static PreparedStatement stsm; 12 13 /** 14 * 这是个出错就回滚回整个事务的起始未知的例子 15 */ 16 17 @Test 18 public void trans1() { 19 20 // 1:准备sql语言 21 String sql1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='张三';"; 22 String sql2 = "UPDATE transfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 23 24 try { 25 // 2:创建连接 26 conn = Jdbcutil.getConnection(); 27 28 // 3:设定事物为手动开启 29 // void setAutoCommit(boolean autoCommit):将此连接的自动提交模式设置为给定状态 30 conn.setAutoCommit(false); 31 32 // 4:执行sql 33 stsm = conn.prepareStatement(sql1); 34 stsm.executeUpdate(); 35 36 stsm = conn.prepareStatement(sql2); 37 stsm.executeUpdate(); 38 39 } catch (Exception e) { 40 // 4:若是上面的语句有任何一条出错,则回滚事务 41 try { 42 conn.rollback(); 43 } catch (Exception e1) { 44 e1.printStackTrace(); 45 } 46 } finally { 47 // 4:若是上面的语句(事务)都没错,则执行事务 48 // void commit():使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 49 // 对象当前持有的所有数据库锁。 50 try { 51 conn.commit(); 52 // 5:关闭连接 53 Jdbcutil.close(conn, stsm); 54 } catch (Exception e) { 55 e.printStackTrace(); 56 } 57 58 } 59 }
3:这是个回滚到事务中的指定位置的方法 例:如果我知道第一笔转账肯定成功,若出错就只会是第二笔出错,所以我会在第一和第二之间的位置设定个保存点:
Savepoint setSavepoint(String name) 在当前事务中创建一个具有给定名称的保存点
然后若是出错,则回滚到该保存点的位置,而之前的语句仍正常执行 void rollback(Savepoint savepoint):
savepoint - 要回滚到的 Savepoint 对象
1 @Test 2 public void test2() { 3 4 // 创建保存点对象 5 Savepoint one = null; 6 7 // 1:设定sql语句 8 // 第一次转账 9 String one1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='张三';"; 10 String one2 = "UPDATE transfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 11 // 第二次转账 12 String two1 = "UPDATE transfer SET accmoney=accmoney-1000 WHERE accName='张三';"; 13 String two2 = "UPDATE tranfer SET accmoney=accmoney+1000 WHERE accName='李四';"; 14 15 try { 16 // 2:创建连接 17 conn = Jdbcutil.getConnection(); 18 19 // 3:设定事务为手动执行 20 conn.setAutoCommit(false); 21 22 // 4:创建PreparedStatement对象。执行sql语句 23 // 执行第一笔转账 24 stsm = conn.prepareStatement(one1); 25 stsm.executeUpdate(); 26 stsm = conn.prepareStatement(one2); 27 stsm.executeUpdate(); 28 29 // 5:设定保存点 30 one = conn.setSavepoint("one"); 31 32 // 执行第二笔转账 33 stsm = conn.prepareStatement(two1); 34 stsm.executeUpdate(); 35 stsm = conn.prepareStatement(two2); 36 stsm.executeUpdate(); 37 38 } catch (Exception e) { 39 // 6:若有语句出错,则回滚到保存点 40 try { 41 conn.rollback(one); 42 } catch (Exception e1) { 43 e1.printStackTrace(); 44 } 45 e.printStackTrace(); 46 } finally { 47 try { 48 // 7:若语句没有错误,则执行事务 49 conn.commit(); 50 // 8:关闭连接 51 Jdbcutil.close(conn, stsm); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 57 }