案例:银行转账问题,数据库如下
相关API
setAutoCommit(boolean autoCommit)
将此连接的自动提交模式设置为给定状态。设置事务是否自动提交如果设置为false,表示手动提交事务
setSavepoint()
在当前事务中创建一个未命名的保存点 (savepoint),并返回表示它的新 Savepoint
对象。
void rollback() ; 回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
java.sql接口 Savepoint public interface Savepoint 保存点的表示形式,保存点是可以从 Connection.rollback
方法引用的当前事务中的点。将事务回滚到保存点时,在该保存点之后所作的全部更改都将被撤消。
// 1. 转账 public void trans1() { String sql_zs = "UPDATE account SET money=money-1000 WHERE name='张三';"; String sql_ls = "UPDATE account SET money=money+1000 WHERE name='李四';"; try { con = JDBCU.getConnection(); // 默认开启的隐士事务 con.setAutoCommit(true);//默认值是true,写不写一样 /*** 第一次执行SQL ***/ pstmt = con.prepareStatement(sql_zs); pstmt.executeUpdate(); /*** 第二次执行SQL ***/ pstmt = con.prepareStatement(sql_ls); pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCU.closeAll(con, pstmt, null); } }
当一方出现问题,这个时候需要管理,除了两者都提交成功外,其他的都回滚原来状态
@Test // 2. 转账,使用事务 public void trans2() { String sql_zs = "UPDATE account SET money=money-1000 WHERE name='张三';"; //故意出错,数据库会出错。 String sql_ls = "UPDATE account SET money=money1+1000 WHERE name='李四';"; try { con = JDBCU.getConnection(); // 默认开启的隐士事务 // 一、设置事务为手动提交 con.setAutoCommit(false); /*** 第一次执行SQL ***/ pstmt = con.prepareStatement(sql_zs); pstmt.executeUpdate(); /*** 第二次执行SQL ***/ pstmt = con.prepareStatement(sql_ls); pstmt.executeUpdate(); } catch (Exception e) { try { // 二、 出现异常,需要回滚事务 con.rollback(); } catch (SQLException e1) { } e.printStackTrace(); } finally { try { // 三、所有的操作执行成功, 提交事务 con.commit(); JDBCU.closeAll(con, pstmt, null); } catch (SQLException e) { } } }
回滚到指定的代码段
// 3. 转账,使用事务, 回滚到指定的代码段 //第一次有错误,而第二次有错误,现在想在第一次和第二次之间设置一个还原点 @Test public void trans() { // 定义个标记 Savepoint sp = null; // 第一次转账 String sql_zs1 = "UPDATE account SET money=money-1000 WHERE accountName='张三';"; String sql_ls1 = "UPDATE account SET money=money+1000 WHERE accountName='李四';"; // 第二次转账 String sql_zs2 = "UPDATE account SET money=money-500 WHERE accountName='张三';"; String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE accountName='李四';"; try { con = JDBCU.getConnection(); // 默认开启的隐士事务 con.setAutoCommit(false); // 设置事务手动提交 /*** 第一次转账 ***/ pstmt = con.prepareStatement(sql_zs1); pstmt.executeUpdate(); pstmt = con.prepareStatement(sql_ls1); pstmt.executeUpdate(); // 回滚到这个位置? sp = con.setSavepoint(); /*** 第二次转账 ***/ pstmt = con.prepareStatement(sql_zs2); pstmt.executeUpdate(); pstmt = con.prepareStatement(sql_ls2); pstmt.executeUpdate(); } catch (Exception e) { try { // 回滚 (回滚到指定的代码段) con.rollback(sp); } catch (SQLException e1) { } e.printStackTrace(); } finally { try { // 提交 con.commit(); } catch (SQLException e) { } JDBCU.closeAll(con, pstmt, null); } }