编程式事务

 事务(Transaction)
  分为编程式事务和声明式事务,此处说明的是编程时事务:
            
        演示银行转账的功能(以此为例):
          1.创建一张表示账号的表
                CREATE TABLE t_account(
                    id INT PRIMARY KEY AUTO_INCREMENT,
                    a_name VARCHAR(50),
                    balance DECIMAL(11,2)//11表示一共有几位,2表示有几位小数
                )
                
          2.向表中插入几个用户
                INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'sunwukong',1000);
                INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'zhubajie',1000);
                INSERT INTO t_account(id,a_name,balance) VALUES(NULL,'shaheshang',1000);
                SELECT * FROM t_account;        
              
          3.#sunwukong向shaheshang转账100元      
                #从sunwukong的账号减去100元
                UPDATE t_account SET balance = balance - 100 WHERE a_name='sunwukong';

                #给shaheshang的账号加上100元
                UPDATE t_account SET balance = balance +100 WHERE a_name = 'shaheshang';
                   
             重新设置为1000元:
                UPDATE t_account SET balance =1000;
                
          4.从java代码中演示上面的案例:
             1.创建Dao类            

  
 1  public class AcountDao {    
 2                     public void update(String name,double money){
 3                         //准备两个变量
 4                         Connection conn = null;
 5                         PreparedStatement ps = null;
 6                         //准备SQL模板
 7                         String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";
 8                         
 9                         try {
10                             conn = JDBCUtil.getConnection();
11                             //获取PreparedStatement
12                             ps = conn.prepareStatement(sql);
13                             //填充占位符
14                             ps.setDouble(1, money);
15                             ps.setString(2, name);
16                             
17                             //执行SQL语句
18                             ps.executeUpdate();
19                             
20                         } catch (SQLException e) {
21                             // TODO Auto-generated catch block
22                             e.printStackTrace();
23                         }finally{
24                             JDBCUtil.close(conn, ps, null);
25                         }
26                     }
27                 }
Dao中进行数据库操作             

            2.测试该DAO              

         public class TestTransaction {
                    private AcountDao accountDao = new AcountDao();
                    
                    @Test
                    public void test() {
                        //从sunwukong账户向shaheshang账户转账100元!
                        //1.从sunwukong账户扣除100元
                        accountDao.update("sunwukong", -100);
                        //2.向shaheshang账户添加100元
                        accountDao.update("shaheshang", 100);
                    }
                }

                //显然上面是可以正常执行的!
                但是如果上面的程序在suwukong减去100元之后,shaheshang加钱之前,出现了异常,如下所示:                    

              //从sunwukong账户向shaheshang账户转账100元!
                        //1.从sunwukong账户扣除100元
                        accountDao.update("sunwukong", -100);
                        int i  =10/0;//添加一个异常
                        //2.向shaheshang账户添加100元
                        accountDao.update("shaheshang", 100);            

        - 在开发中我们的一个业务往往需要同时操作多个表,这些操作往往是不可分割,业务中的对数据库的多次操作,
          要么同时成功,要么全都失败。
       
        - 事务的特性(ACID):
            原子性(atomicity)
                一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
                
            一致性(consistency)
                事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

            隔离性(isolation)
                一个事务的执行不能被其他事务干扰。
                    即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
                    
            持久性(durability)
                持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
                    接下来的其他操作或故障不应该对其有任何影响。
                    
        - 操作事务的基本步骤:
            1.开启事务
                - 开启事务以后,我们只后的所有操作将都会在同一个事务当中
            2.操作数据库
                - 开启事务以后再去操作数据库,所有操作将不会直接提交到数据库中
            3.提交事务
                - 将修改应用到数据库
            4.回滚事务
                - 数据库操作过程中出现异常了,回滚事务,回滚事务以后,数据库变成开启事务之前的状态
        
        - mysql中的事务控制
            #开启事务
                START TRANSACTION
            #回滚事务
                ROLLBACK            
            #提交事务
                COMMIT
            
        - JDBC中的事务主要通过Connection对象来控制的
            1.开启事务
                void setAutoCommit(boolean autoCommit) throws SQLException;
                - 设置事务是否自动提交,默认是自动提交
                - 设置事务手动提交
                    conn.setAutoCommit(false);
                
            2.提交事务
                void commit() throws SQLException;
                - 提交事务
                conn.commit()
            
            3.回滚事务
                void rollback() throws SQLException;
                - 回滚事务
                conn.rollback()
                
        - 事务控制的格式:         

 1 ·      //创建一个Connection
 2             Connection conn = null;
 3             
 4             try{
 5                 
 6                 //获取Connection
 7                 conn = JDBCUtils.getConnection();
 8                 
 9                 //开启事务
10                 conn.setAutoCommit(false);
11                 
12                 //对数据库进行操作
13                 
14                 //操作成功,提交事务
15                 conn.commit();
16                 
17             }catch(Exception e){
18                 e.printStackTrace();
19                 
20                 //回滚事务
21                 try {
22                     conn.rollback();
23                 } catch (SQLException e1) {
24                     e1.printStackTrace();
25                 }
26                 
27             }finally{
28                 JDBCUtils.close(conn, null, null);
29             }   

    - 注意:我们在同一个事务中使用的数据库连接(Connection)必须是同一个,否则事务还是不作用!    
        所以此时原来的AcountDAO中的update方法要改为如下所示:        

  
 1 public class AcountDao {    
 2                 public void update(Connection conn,String name,double money){
 3                     //准备两个变量
 4                     PreparedStatement ps = null;
 5                     //准备SQL模板
 6                     String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";
 7                     
 8                     try {
 9                         //获取PreparedStatement
10                         ps = conn.prepareStatement(sql);
11                         //填充占位符
12                         ps.setDouble(1, money);
13                         ps.setString(2, name);
14                         
15                         //执行SQL语句
16                         ps.executeUpdate();
17                         
18                     } catch (SQLException e) {
19                         // TODO Auto-generated catch block
20                         e.printStackTrace();
21                     }finally{
22                         //此时也不能在这里关闭数据库连接了,而是在外边统一关闭
23                         JDBCUtil.close(null, ps, null);
24                     }
25                 }
26             }
Dao类中更改后代码
  
 1 @Test
 2     public void test() {
 3         Account account=new Account();
 4         
 5         Connection conn = JDBCUtil.getConnection();
 6         try {
 7             conn.setAutoCommit(false);
 8             account.update(conn,"孙悟空", -100);
 9             int i=10/0;
10             account.update(conn,"猪八戒", 100);
11             conn.commit();
12         } catch (SQLException e) {
13             try {
14                 conn.rollback();//fa
15             } catch (SQLException e1) {
16                 // TODO Auto-generated catch block
17                 e1.printStackTrace();
18             }
19         }
20         if(conn!=null){
21             try {
22                 conn.close();
23             } catch (SQLException e) {
24                 // TODO Auto-generated catch block
25                 e.printStackTrace();
26             }
27         }    
28     }
更改后测试类代码
原文地址:https://www.cnblogs.com/kangxingyue-210/p/7456412.html