You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置connection.setAutoCommit(false)后插入再回滚,数据仍入库的原因?

问题:设置connection.setAutoCommit(false)后未提交却仍插入数据?

环境信息

  • Windows 11 x64
  • Oracle Database 21c Express Edition
  • Java/JDK 19
  • IntelliJ IDEA 2023.x

确认Oracle版本的SQL语句

select banner from v$version;
-- Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production

测试用Java代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.ZoneId;

public class VyInsert {

    public static void main(String[] args) {
        try (Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "12345678")) {

            if (connection != null) {
                connection.setAutoCommit(false);
                System.out.println("Connected to the database.");
                String query = "insert into SYSTEM.CUSTOMER (ID, NAME, EMAIL, CREATED_DATE) values (?, ?, ?, ?)";
                PreparedStatement preparedStatement = connection.prepareStatement(query);
                preparedStatement.setInt(1, 17);
                preparedStatement.setString(2, "Nguyen Thu Hang23");
                preparedStatement.setString(3, "anhtrangmuathu32@gmail.com");
                preparedStatement.setObject(4, LocalDate.now(ZoneId.of("America/Montreal")));
                // preparedStatement.setObject(4, LocalDate.now(ZoneId.of("Asia/Ho_Chi_Minh")));
                preparedStatement.executeUpdate();
                // connection.commit();
                //connection.setAutoCommit(true);
            } else {
                System.out.println("Failed to make connection.");
            }

        } catch (SQLException sqlException) {
            System.err.format("SQL State: %s\n%s", sqlException.getSQLState(), sqlException.getMessage());
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

}

疑问

为何设置connection.setAutoCommit(false),执行插入操作后未显式提交,数据仍被插入到数据库中?

原因分析与解决

核心原因是你用了try-with-resources语法声明Connection对象,这个语法会在代码块执行完毕后自动调用connection.close()方法。而Oracle JDBC驱动的默认行为是:当关闭一个存在未提交/未回滚事务的连接时,会自动执行提交操作,而非回滚。这就导致你没写commit(),数据还是被保存到了数据库。

解决方法有两种:

  1. 显式回滚:在executeUpdate()之后添加connection.rollback();语句,这样即使连接关闭,事务已经被回滚,数据不会插入。
  2. 修改驱动行为:在JDBC URL中添加oracle.jdbc.rollbackOnClose=true参数,让驱动在关闭未提交连接时自动回滚事务。修改后的URL示例:
    jdbc:oracle:thin:@localhost:1521:XE?oracle.jdbc.rollbackOnClose=true
    

另外需要注意:Oracle驱动的这个默认提交行为是设计如此,并非bug,目的是避免意外丢失未明确处理的事务数据。

内容的提问来源于stack exchange,提问作者Đỗ Như Vỹ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:01:18