JDBC的autoCommit为true时,其事务管理测试

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LeonWang_Fly/article/details/50116961

前述:事务做为数据库操作特别重要的一方面,不做过多赘述。spring框架使用太久后总忽略一些比较原始的东西,老项目中又使用了这些,看到一些东西总感觉迷惑。比如当使用jdbc调用一个存储过程,该存储过程又有很多子sql语句时,若存储过程出现异常,执行结果如何?猜测会整个回退,但是autoCommit不是自动提交吗?
(jdbc的连接connection默认自动提交autoCommit为ture)
下面就开启探究之旅。。。。。。

测试/验证思路:

1.测试连接获取到之后,进行连续多个CRUD操作,查看操作后期异常和全程无异常的情况。
2.测试连接获取到之后,进行调用存储过程,存储过程中多个CRUD操作(存储过程中无commit语句),查看操作后期异常和全程无异常的情况。
3.测试连接获取到之后,进行调用存储过程,存储过程中多个CRUD操作(存储过程中无commit语句),查看操作后期异常和全程无异常的情况。
此处只为测试,忽略代码是否优美

首先建立测试表,注意两张表的字段长度是不一样的。

create table TEST_LEON_T1(name varchar2(20));
create table TEST_LEON_T2(name varchar2(5));

java代码如下:

public class Test {
    public Connection conn ;
    public static void main(String[] args) {
        String name = "abc";
        testInsert(name);
    }
    //测试连续插入
    public static void testInsert(String name){
        Test test = new Test();
        try {
            test.initConnction();
            String sql = "insert into TEST_LEON_T1(name) values(?)";
            PreparedStatement ps = test.conn.prepareStatement(sql);
            ps.setString(1, name);
            ps.execute();
            String sql2 = "insert into TEST_LEON_T2(name) values(?)";
            PreparedStatement ps2 = test.conn.prepareStatement(sql2);
            ps2.setString(1, name);
            ps2.execute();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            test.close();
        }
    }
    //测试调用存过
    public static void testProcedure(String name){
        Test test = new Test();
        try {
            test.initConnction();
            String sql = "{call TEST_LEON_P1(?)}";
            CallableStatement cs = test.conn.prepareCall(sql);
            cs.setString("name", name);
            cs.execute();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            test.close();
        }
    }
    public void initConnction() throws ClassNotFoundException, SQLException{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        String user = "leon";
        String pwd = "leon";
        String url = "jdbc:oracle:thin:@127.0.0.1:1522:leon";
        conn = DriverManager.getConnection(url,user,pwd);
    }
    public void close(){
        if(conn!=null)
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
}

1. main调用testInsert(“leon”)执行,结果为全部插入。

2. main调用testInsert(“zhangsan”)执行,结果表TEST_LEON_T1数据插入,表TEST_LEON_T2数据无插入。

3. 调整testInsert代码,在finally中加入以下代码继续执行以上两步,发现结果没有变化,第二个测试中TEST_LEON_T1数据仍然插入进去了

            try {
                test.conn.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }


结论:
JDBC执行sql默认提交,每一个sql语句执行后提交一次。(下面通过存储过程的调用进行验证)

存过无commit

create or replace PROCEDURE TEST_LEON_P1(name in varchar2) as
begin
  insert into TEST_LEON_T1 (name) values (name);
  insert into TEST_LEON_T2 (name) values (name);
end;

1. main调用testProcedure(“leon”)执行,结果为全部插入。

2. main调用testProcedure(“zhangsan”)执行,结果两表都没有数据插入。

3. 再调整一下存储过程,在两条sql语句中加入commit,main调用testProcedure(“zhangsan”)执行,结果表TEST_LEON_T1数据插入,表TEST_LEON_T2数据无插入。


这个结果证明:
jdbc执行sql时,连接默认设置autoCommit为true,即默认自动提交,自动提交意味着每执行一条sql进行commit一次,commit提交的最小单位为一条sql语句,无论是CRUD操作还是调用存储过程,都算作一个基本提交单元。

猜你喜欢

转载自blog.csdn.net/LeonWang_Fly/article/details/50116961
今日推荐