JDBC中,Connection回滚失败怎么办?

zho*_*udu 5 java jdbc

接口 java.sql.Connection 的 Java 文档对 close() 方法说:“强烈建议应用程序在调用 close 方法之前显式提交或回滚活动事务。如果调用 close 方法并且有一个活跃的交易,结果是实现定义的。”

这就产生了一个微妙但严重的问题:如果我调用了一个Connection 的rollback() 方法,但是这个方法失败了(比如发生了超时),那么我可以调用这个Connection 的close() 方法吗?当我调用 close() 方法时,是否可能仍然存在活动事务,因此结果是实现定义的,因此可以提交事务?

如果 rollback() 失败,我可以选择不调用 close() 方法,但这可能会导致 JDBC 资源没有被释放。此外,也许最终会调用 close() 方法(也许当 Connection 对象被垃圾收集时)。如果是这种情况,那么这种方法将无济于事。

那么,当 Connection 的 rollback() 方法失败时我该怎么办?如果rollback() 方法失败了,我还能调用这个Connection 的close() 方法吗?

Ste*_*n C 5

如果我调用了rollback()a的方法Connection但是这个方法失败了(比如发生了超时),那么我可以调用这个的close()方法Connection吗?

根据 JDBC 规范,SQLTransactionRollbackException是一个 Transient SQLException

SQLException在先前失败的操作在没有应用程序级功能的任何干预的情况下重试操作时可能会成功的情况下,将抛出Transient 。经过短暂SQLException以外SQLTransientConnectionException时,应用程序可以假设连接仍然有效。

因此,如果rollback()失败SQLTransactionRollbackException,您应该能够close()连接,或重试rollback(). (如果您调用close(),调用之后驱动程序提交事务rollback()将是不正常的。)

但是,如果rollback()失败,SQLTransientConnectionException则连接将无效。调用close()可能会失败...或者它可能会提交事务1。谨慎的做法是放弃Connection,并相信数据库会自动回滚事务。或者,如果您可以(从驱动程序的文档等中)确定 aclose() 不会提交事务,则调用close().

在后一种情况下,我认为我们应该假设当 JDBC 驱动程序检测到连接丢失时,它会Socket尽可能释放和其他资源。Socket网络连接已中断的A无法“重新打开”,因此没有必要继续使用它。

如果我们没有调用close()并且只是忘记了Connection(在回滚失败之后),那么资源泄漏可能无关紧要,因为:

  • 数据库连接失败应该很少发生,
  • Java GC 应该最终完成Connection并释放相关的Socket等等。

1 - 理论上。JDBC Javadocs 说如果您close()与活动事务建立连接,会发生什么情况是不确定的。但是值得检查您正在使用的特定驱动程序的文档。