关闭

关于jdbc事务自动提交

标签: 异常jdbcjava事务
256人阅读 评论(0) 收藏 举报
分类:

实现jdbc事务流程:

  1. 建立数据库连接;
  2. 将autoCommit设置为false;
  3. 执行sql语句;
  4. 提交;
  5. 处理异常,如果sql语句执行失败则执行rollBack;

其中,如果执行sql语句过程中抛出异常,不调用commit,提交不会发生,但如果最后执行setAutoCommit(true),提交还是有可能发生。rollback必须显式调用,即便发生异常,执行到setAutoCommit(true)时,提交会自动进行,事务可能执行一一部分。
典型示例如下:

import java.sql.*;
public class TestTranslation {
    public static void main(String args[])
    {
        Statement stmt=null;
        Connection conn=null;
        try{
            Class.forName("com.mysql.jdbc.Driver");
            conn=DriverManager.getConnection("jdbc:mysql://localhost/javatest?user=cheng&password=***");
            conn.setAutoCommit(false);
            String sqlLine1="update tbl_currency set currency=currency-200,last_modified=current_timestamp WHERE account='A' and currency>=200";
                st=conn.createStatement();
                int r1=st.executeUpdate(sqlLine1);
                String sqlLine2="update tbl_currency set currency=currency+200,last_modified=current_timestamp WHERE account='B'";
                int r2=st.executeUpdate(sqlLine2);
                if(r1==1&&r2==1){
                    conn.commit();
                    System.out.println("A2B转账成功");
                }
                else{
                    //conn.rollback();
                    System.out.println("A2B转账失败");
                }
        }
        catch(ClassNotFoundException e){
            System.out.println("class not found");
        }
        catch(SQLException e){
            System.out.println("SQL exception");
            e.printStackTrace();
        }
        finally{
            if(null!=conn){
                try{
                    conn.setAutoCommit(true);
                    conn.close();
                }
                catch(SQLException e){
                    System.out.println("close sql connection failed");
                }
            }
            if(null!=stmt){
                try{
                    stmt.close();
                }
                catch(SQLException e){
                    System.out.println("close statement failed");
                }
            }
        }
    }
}

这段代码是一个银行账户问题,即将A中的钱转入200到B账户中,其中有个条件,如果A账户余额小于200则不进行转账,最后对结果进行检查。如果A账户中的钱小于200,第一条语句返回0,进入转账失败流程,但不会抛出异常,如果注释掉conn.rollBack(),当执行到finally中的conn.setAutoCommit(true)时,这两条语句还是会被commit,最终的结果就是其中尽管A中的钱不再减少,但B中的钱还是会增加,所以,在这种情形下,显式调用rollBack是必需的。
下面的代码,还是被因为调用setAutoCommit而提交。

import java.sql.*;
public class TestTranslation {
    /**
     * @param args
     */
    public static void main(String args[])
    {
        Statement stmt=null;
        Connection conn=null;
        try{
            Class.forName("com.mysql.jdbc.Driver");
            conn=DriverManager.getConnection("jdbc:mysql://localhost/test?user=cheng");
            conn.setAutoCommit(false);
            stmt=conn.createStatement();
            stmt.executeUpdate("insert into tbl_test values('liyi',26,'female')");
            stmt.executeUpdate("insert into tbl_test values('liyi',26,'female')");
            conn.commit();
        }
        catch(ClassNotFoundException e){
            System.out.println("class not found");
        }
        catch(SQLException e){
            try {
                conn.rollback();//如果这里没有rollback,执行到finally中的setAutoCommit时,执行成功的前一句依然会被提交
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            System.out.println("SQL exception");
            e.printStackTrace();
        }
        finally{
            if(null!=conn){
                try{
                    conn.setAutoCommit(true);
                    conn.close();
                }
                catch(SQLException e){
                    System.out.println("close sql connection failed");
                }
            }
            if(null!=stmt){
                try{
                    stmt.close();
                }
                catch(SQLException e){
                    System.out.println("close statement failed");
                }
            }
        }
    }
}

其中名字是主键,第二句在第一句执行后显然应该失败,抛出异常,如果异常处理中没有rollback,执行到finally中的setAutoCommit时还是会提交第一句。
所以,尽管有异常,如果不显式调用rollback,事务还是可能执行一部分。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9018次
    • 积分:225
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章分类