JDBC和Oracle conn.commit和conn.setAutocommit无法正常工作

我已经创建了一个DBManager类,如下所示

public class DBManager { public static String DRIVER = "oracle.jdbc.driver.OracleDriver"; public static String URL = "jdbc:oracle:thin:@//localhost:1521/DB"; public static String USERNAME = "afsweb"; public static String PASSWORD = "afsweb"; public static String DOCDBUSERNAME = "docdb"; public static String DOCDBPASSWORD = "docdb"; public static int PORT = 1521; //static Logger log = Logger.getLogger(ExcelDBManager.class.getName()); public static Connection getConnection(String url ,String username, String password){ try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } Connection con = null; try { con = DriverManager.getConnection(url,username,password); con.setAutoCommit(false); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return con; } 

我有方法截断表中的行

 public static void truncate() throws SQLException{ conn = DBManager.getConnection(DBManager.URL, DBManager.USERNAME, DBManager.PASSWORD); System.out.println(conn.getAutoCommit() +""); Statement pstmnt = null; ResultSet rs = null; try{ pstmnt = conn.createStatement(); pstmnt.executeQuery("truncate table bd_vehicles_temp_1"); System.out.println("Query Executed"); } catch(SQLException e){ e.printStackTrace(); } finally{ try{ if(rs !=null){ rs.close(); } if(pstmnt != null){ pstmnt.close(); } if(conn != null){ conn.close(); } } catch(SQLException e) { e.printStackTrace(); } } } 

现在我没有在truncate()方法中编写conn.commit。 我也将setAutocommit设为false。 即便如此,这些变化也反映在数据库中。

在执行上述方法时,我输出为

 false Query Executed 

这意味着我的连接自动提交模式为false。 截断方法所做的更改仍反映在数据库中。 可能的原因是什么? 我正在使用Oracle数据库。

提前致谢 !

TRUNCATE是一种隐式提交的数据定义语言(DDL)命令。 如果您使用DELETE语句,它就不会提交任何内容。

 // Deletes ALL Rows; No WHERE Clause pstmnt.executeQuery("DELETE FROM bd_vehicles_temp_"); 

TRUNCATE是一个DDL语句的原因是它直接删除表数据而不将其复制到回滚表空间 。 这就是为什么TRUNCATE更快但无法回滚的原因。

编辑 :(为什么我的INSERTs也提交?)

那是因为你在没有调用Connection#rollback()的情况下关闭了你的Connection

如果在没有显式提交回滚的情况下关闭Connection ; JDBC在此处不强制要求任何内容,因此行为取决于数据库供应商。 对于Oracle,会发出隐含提交

强烈建议应用程序在调用close方法之前显式提交或回滚活动事务。 如果调用close方法并且存在活动事务,则结果是实现定义的。

所以,只需在finally块中关闭Connection之前rollback()您的更改

 pstmnt = conn.createStatement(); pstmnt.executeQuery("DELETE FROM bd_vehicles_temp_1"); System.out.println("Query Executed"); conn.rollback(); System.out.println("Changes rolled back"); 

TRUNCATE TABLE基本上不允许以正常方式提交/回滚。 根据此文档 :

因为Truncate是DDL,它在它执行之前发出COMMIT,之后发出另一个COMMIT,因此不可能回滚事务。

如果要在事务中执行此操作,请使用DML – 例如,正常的DELETE FROM ...语句。

Oracle truncate命令是DDL,它隐式发出提交。 见http://docs.oracle.com/cd/E17952_01/refman-5.5-en/truncate-table.html

自动提交行为取决于您使用的基础数据库。 不幸的是,Oracle的JDBC驱动程序默认情况下会在close()上提交。