在检索out参数的值之前应该调用commit()吗?

时间:2017-11-10 15:59:16

标签: java sql oracle procedure autocommit

在编写java JDBC代码以调用存储过程时我正在使用con.setAutoCommit(false);我的问题是以下方法的区别是什么:

方法-1:

        con = DBConnection.getConnection();
        con.setAutoCommit(false);
        stmt= con.prepareCall("{call updateEmp(?,?,?,?,?,?)}");
        stmt.setInt(1, id);
        stmt.setString(2, name);
        stmt.setString(3, role);            
        stmt.registerOutParameter(6, java.sql.Types.VARCHAR);

        stmt.executeUpdate();
        con.commit();
        //read the OUT parameter AFTER commit
        String result = stmt.getString(6);

或方法-2:

        // Read the OUT parameter BEFORE commit
        String result = stmt.getString(6);
        con.commit();

5 个答案:

答案 0 :(得分:1)

我认为这取决于您调用的存储过程是否自己提交。我期望一个更新程序,它接受params,并设置params在内部进行提交或回滚。

在这种情况下,调用setAutoCommit(true)或调用con.commit()将无效,并且无论何时调用stmt.getString(6),out参数都将具有值。如果存储过程本身没有提交,如果在调用stmt.getString(6)之后调用con.commit(),我希望你的out参数为null。

答案 1 :(得分:1)

主要区别在于您持有的交易时间超过了必要的时间。您应该尽可能快地尝试提交,以尽量减少阻止其他事务的可能性。特别是如果您正在执行诸如传输BLOB或大文本字段之类的操作,这可能会占用大量事务日志空间(并且需要更多时间通过线路传输)。

答案 2 :(得分:1)

区别在于异常处理。如果getString抛出异常,则不执行以下提交。后果取决于当前交易是否有任何变化**。如果您要跟踪代码的两个版本(没有抛出异常)然后比较两个跟踪文件,除非您留下某种标记,否则您将无法分辨创建每个跟踪的代码版本(或保留每个用户进程的spid。)

你必须问自己一个问题:即使抛出异常,我还想提交吗?然后你就会知道如何编写代码。

**您的连接始终打开一个事务。有些交易有变化而其他交易没有。

答案 3 :(得分:0)

在我看来,在out参数是一个简单类型的情况下,它更大程度上是一种风格问题。但是,out参数可以是例如光标。在自动提交的情况下,仅当光标类型输出参数或存储过程返回的所有结果集都关闭时,才会发生提交操作。如果在光标完全获取之前发出提交,则数据一致性是有问题的。为了避免这种歧义,我建议在读完所有输出参数后提交/回滚事务。

答案 4 :(得分:0)

在一个答案中总结上述答案,以便快速总结:

1-如果提交,在读取所有输出参数之前,数据一致性是有问题的。所以这里方法-2是不可取的。

2-假设在读取输出参数时发生异常,则交易不会被提交。另一方面,如果我们希望在不关心out参数的情况下提交事务,我们可以在读取之前提交。

3-在方法-2中,我们阻止交易更长时间。在上面的示例代码中,它并不是什么大问题,但在提交之前我们做了很多事情可能是个问题。