设置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(),数据还是被保存到了数据库。
解决方法有两种:
- 显式回滚:在
executeUpdate()之后添加connection.rollback();语句,这样即使连接关闭,事务已经被回滚,数据不会插入。 - 修改驱动行为:在JDBC URL中添加
oracle.jdbc.rollbackOnClose=true参数,让驱动在关闭未提交连接时自动回滚事务。修改后的URL示例:jdbc:oracle:thin:@localhost:1521:XE?oracle.jdbc.rollbackOnClose=true
另外需要注意:Oracle驱动的这个默认提交行为是设计如此,并非bug,目的是避免意外丢失未明确处理的事务数据。
内容的提问来源于stack exchange,提问作者Đỗ Như Vỹ
相关产品推荐
相关产品推荐

