【求助帖】【已自行解决】java批处理的commit()方法有什么用?

我使用的数据库是Oracle。
以下的代码让我很疑惑不解。

这代码看着挺多其实不难。

public class Main {
     
    private static final String DBDRIVER="oracle.jdbc.driver.OracleDriver";
    private static final String DBURL="jdbc:oracle:thin:@localhost:1521:orcl ";
    private static final String USER="scott";
    private static final String PASSWORD="tiger";

    public static void main(String[] args)throws Exception {
     

        Class.forName(DBDRIVER);//加载驱动程序
        Connection conn = DriverManager.getConnection(DBURL, USER, PASSWORD);//连接数据库
        Statement stmt=conn.createStatement();//创建数据库操作对象
        conn.setAutoCommit(false);//取消自动提交
        try {
     
            stmt.addBatch("INSERT INTO member(mid,name)VALUES (myseq.nextval,'尘封')");
            stmt.addBatch("INSERT INTO member(mid,name)VALUES (myseq.nextval,'尘封')");
            //【下面这行语句有错误,我故意多写了一个“'”】,由于使用了事务控制,所有批处理的更新语句将都不会执行
            stmt.addBatch("INSERT INTO member(mid,name)VALUES (myseq.nextval,'尘'封')");
            stmt.addBatch("INSERT INTO member(mid,name)VALUES (myseq.nextval,'尘封')");
            stmt.addBatch("INSERT INTO member(mid,name)VALUES (myseq.nextval,'尘封')");
            int[] result = stmt.executeBatch();//执行批处理
            System.out.println(Arrays.toString(result));//输出数组内容
            conn.commit();//手动提交(这行代码有啥意义吗?)
        }catch (Exception e){
     
            e.printStackTrace();
            conn.rollback();//如果出现异常,则进行回滚
        }
        conn.close();//关闭数据库连接
    }//jdbc关闭自动提交. 在对数据库的操作未提交时,当conn.close()时,会默认先提交事务,再关闭连接.
}

关闭自动提交是使用事务控制的前提。

所以我把自动提交关闭了,但是让我不解的是commit()方法存在的意义是什么。
Question1?:
commit()方法就是把数据提交。我把手动提交的那行代码注释了,执行完程序后,我看了一下member表,里面的数据更新了,这难道不是说明数据已经提交了吗?既然提交了,你commit()又提交一次这不是没有意义嘛。
Question2?:
我在核心技术上看到,这么一句话。
默认情况下,数据库连接处于自动提交模式,即每个sql语句一旦被执行便被提交给数据库。一旦命令提交,就无法对它进行回滚操作。

我把代码rollback();方法那一行注释掉,运行程序发现,表中的数据就更新了,我取消注释再次运行,这次数据没有变化,那么数据难道是先更新再回滚的吗????(误解已划掉)

以上就说明,我的代码是可以回滚的,既然可以回滚,就说明数据没有提交,但是我在表中已经看到了数据的确是更新了呀。那这算怎么回事???

探索研究:
通过今天的发现insert delete 这种是DML语言。
他们所执行的操作有一个叫回滚段.的东西。

就是说,在执行DML语言修改数据前,会先把当前数据保存在回滚段里面,然后再执行DML语言修改数据后,你可以调用rollback()方法进行回滚,恢复到修改之前的数据。

在commit()方法之前也就是提交之前,你所作的DML更新修改都是保存在内存中的,并没有到数据库本身,只有提交(commit()方法)之后才可以。

关于第一个问题的解答:虽然我注释了commit()方法,但是程序结束后,无论通过select指令还是idea表查看,数据的确更新了,说明数据是提交了的。(因为DML语言如果不提交,你所做的修改只保存在内存里,你根本就看不到。)
原因就在于close()方法,关闭数据库的连接时会默认对事务进行一次提交。(先提交然后再关闭数据库连接)
所以这也就能说明,为什么没有commit()也能更新数据的原因了。

commit()执行后,会提交数据并清空回滚段,所以调用了commit()方法后,就没有办法进行回滚了。

而关于问题2就更好解答了。
我注释了rollback()(回滚方法),运行程序后还能更新数据就是因为close()方法,关闭数据库会自动提交一次事务。
提交之后数据就更新到了数据库里,所以我才能看到数据更新过了。

你可能感兴趣的:(java,oracle,数据库)