6

我制作了一个 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

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

提前致谢 !

4

4 回答 4

10

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

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

原因TRUNCATE是 DDL 语句是直接删除表数据而不将其复制到Rollback Tablespace中。这就是为什么TRUNCATE更快但不能回滚的原因。

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

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

如果连接在没有明确提交回滚的情况下关闭;JDBC 在这里没有特别要求任何东西,因此行为取决于数据库供应商。在 Oracle 的情况下,会发出隐式提交

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

所以,只是在finally块中关闭连接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");
于 2013-08-14T13:58:27.437 回答
4

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

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

如果您想将此作为事务的一部分,请改用 DML - 例如普通DELETE FROM ...语句。

于 2013-08-14T13:58:52.947 回答
3

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

于 2013-08-14T13:59:54.487 回答
2

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

于 2013-08-14T13:58:53.760 回答