如果 java.sql.Connection#commit() 抛出异常,是否需要回滚?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3790922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:23:08  来源:igfitidea点击:

Is rollback needed if java.sql.Connection#commit() throws exception?

javajdbcconnectionrollback

提问by dcp

According to JAVA documentation, Connection#commit()can throw SQLException. My question is whether or not a rollback should still be issued in this scenario.

根据JAVA文档Connection#commit()可以抛出SQLException。我的问题是在这种情况下是否仍应发出回滚。

For example:

例如:

Connection con = null;
try {
    // assume this method returns an opened connection with setAutoCommit(false)
    con = createConnection(); 

    // do DB stuff

    con.commit();
} catch (SQLException e) {
    if (con != null) {
        // what if con.commit() failed, is this still necessary,
        // will it hurt anything?
        con.rollback();
    }
} finally {
    if (con != null) {
        con.close();
    }
}

I actually wrapped the con.rollback() call into another method which ignores any exceptions thrown by it, so I think I'm ok here. I just wondered if this was the best way of handling things.

我实际上将 con.rollback() 调用包装到另一个方法中,该方法忽略了它抛出的任何异常,所以我认为我在这里没问题。我只是想知道这是否是处理事情的最佳方式。

采纳答案by Nikita Rybak

I would do explicit rollback just for clean-up purposes. Although changes won't be persisted in db either way, it seems nice to explicitly let database know that you're done here. Just like the way you close connection explicitly, without waiting for Connection object to be garbage-collected.

我会为了清理目的而进行显式回滚。尽管更改不会以任何方式持久保存在 db 中,但显式地让数据库知道您已在这里完成似乎很好。就像您显式关闭连接的方式一样,无需等待 Connection 对象被垃圾收集。

This is, obviously, not a technical answer and I would also be interested to learn whether there's a practical point in doing so.

显然,这不是技术答案,我也有兴趣了解这样做是否有实际意义。

回答by MosheElisha

Rollback is important even if commit failed, according to the Java 1.6 JDBC docs:

根据Java 1.6 JDBC 文档,即使提交失败,回滚也很重要:

It is strongly recommended that an application explicitly commits or rolls back an active transaction prior to calling the close method. If the close method is called and there is an active transaction, the results are implementation-defined.

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

This means that if you do not explicitly invoke rollback, some JDBC implementation might invoke commit before closing the connection.

这意味着如果您没有显式调用回滚,某些 JDBC 实现可能会在关闭连接之前调用提交。

Another good reason to rollback is as Xepoch suggested and when using a connection pool it is even more important. When getting a connection from a connection pool, most implementations will execute connection.setAutoCommit(defaultAutoCommit)before giving you the connection and according to the JavaDocs:

另一个回滚的好理由是 Xepoch 建议的,当使用连接池时,它甚至更重要。从连接池获取连接时,大多数实现将connection.setAutoCommit(defaultAutoCommit)在为您提供连接之前执行,并且根据 JavaDocs:

If this method is called during a transaction and the auto-commit mode is changed, the transaction is committed

如果在事务期间调用此方法并更改自动提交模式,则提交事务

If the connection.rollback()throws an exception - then it is a tricky one...

如果connection.rollback()抛出异常 - 那么这是一个棘手的......

回答by Jé Queue

"Returns an open connection?" If that connection is shared in a pool (and could be in the future) you don't want another transaction committing your earlier work. I've seen MANY customer/solution cases of plugging in pooled connection driver that comply with JDBC interfaces and Connection.close()can also be used to just return the Connection back to a pool.

“返回一个打开的连接?” 如果该连接在池中共享(并且可能在将来共享),则您不希望另一个事务提交您之前的工作。我见过许多插入符合 JDBC 接口的池化连接驱动程序的客户/解决方案案例,Connection.close()也可用于将连接返回到池中。

Also, better try{}catch{}your rollback()(edit, just read your whole post, but I always like to log an exception on rollback)

此外,更好的try{}catch{}rollback()(编辑,刚刚看了你的后整体,但我总是喜欢登录回滚一个例外)

回答by Romain Hippeau

The usual way I do this is:

我这样做的通常方法是:

boolean bSuccess = false;
Connection con = null;
try {
    // assume this method returns an opened connection with setAutoCommit(false)
    con = createConnection(); 

    // do DB stuff

    bSuccess = true;
} catch (SQLException e) 
{
}
finally 
{
    try
    {
       if (con != null) 
       {
          if(bSuccess)
             con.commit()
          else
             con.rollback();

          con.close();
       }
    }
    catch(SQLException sqle)
    {
      log("Log the error here");
      // do nothing we tried
    }
}

That being said I have never seen a commit or a rollback fail if the queries worked.
If you have pending transactions then most databases have tools to free them. Most app servers will keep retrying the commits and rollbacks until they can connect.

话虽如此,如果查询有效,我从未见过提交或回滚失败。
如果您有待处理的事务,那么大多数数据库都有释放它们的工具。大多数应用服务器会不断重试提交和回滚,直到它们可以连接为止。

You might want to look at this post: Is it necessary to write ROLLBACK if queries fail?

您可能想看看这篇文章:如果查询失败,是否有必要编写 ROLLBACK?