【问题标题】:JDBC and Oracle conn.commit and conn.setAutocommit not working properlyJDBC 和 Oracle conn.commit 和 conn.setAutocommit 无法正常工作
【发布时间】:2013-08-16 12:33:00
【问题描述】:

我已经做了一个如下图所示的 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 数据库。

提前致谢!

【问题讨论】:

    标签: java jdbc oracle11g connection


    【解决方案1】:

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

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

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

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

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

    如果 Connection 在没有明确的 commitrollback 的情况下关闭; JDBC 在这里没有特别要求任何东西,因此行为取决于数据库供应商。在 Oracle 的情况下,会发出一个隐含的 commit

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

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

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

    【讨论】:

    • @AbhishekSingh 我已将我的回复添加为我的答案的更新。请看一下。
    【解决方案2】:

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

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

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

    【讨论】:

    • @AbhishekSingh:插入?我以为你想删除?
    • 这是一个不同的场景,我在插入行时遇到同样的问题
    • @AbhishekSingh:那么我认为值得在另一个问题中提出这个问题。您的问题完全是关于 TRUNCATE TABLE 的,它有一个非常自然的解释 - 不一定适用于 INSERT。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 你确定是这个原因吗?即使我插入,我也会得到相同的结果!
      • @AbhishekSingh 据我所知,自动提交标志不会改变 oracle 驱动程序的任何内容,因为连接一旦关闭就会提交。
      • 有任何来源吗?因为在那种情况下我将不得不做 conn.rollback !
      • 以前有一个 wiki 页面,但现在已删除。我正在寻找来源。但是,如果您确认了该行为,那么您可以做出相应的计划。
      • 会使用 conn.rollback 吗?
      猜你喜欢
      • 2013-08-26
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2017-02-17
      • 2021-08-02
      • 2013-08-01
      • 2011-10-10
      • 2017-05-16
      相关资源
      最近更新 更多