在JDBC中,当自动提交是错误的并且没有设置明确的保存点时,回滚是好的样式还是浪费?
假设你有以下代码:
Connection conn; try { conn = ... // get connection conn.setAutoCommit(false); ... // Do some modification queries and logic conn.commit() } catch(SQLException e) { conn.rollback() // Do we need this? conn.close() }
在这段代码中,如果有一个exception,closures连接(因为自动提交是closures的),还是显式的回滚,然后closures连接,是否更好? 没有保存点。
我觉得添加回滚调用是有意义的,因为:
1)未来有人可能会添加保存点,但忘记添加回滚
2)它提高了可读性
3)不应该花费任何东西,对吧?
但显然,这些都不是特别引人注目。 任何标准的做法?
注意:我知道在closures和回滚时需要重复try / catch。 实际上我有一个中间件抽象数据库访问和照顾,但我想知道是否添加它是多余的。
正常的习惯用法如下:
public void executeSomeQuery() throws SQLException { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) { // Fire transactional queries here. connection.commit(); } catch (SQLException e) { connection.rollback(); throw e; } } }
请注意,当try
块完成时,Java 7的try-with-resources语句总是隐式地调用资源的 close()
,就好像它发生在finally
。
当涉及池连接时,调用rollback()
也是必需的。 即,它将重置连接的事务状态。 汇集连接的close()
不会这样做,只有commit()
和rollback()
会这样做。 不调用rollback()
可能会导致池连接的下一个租约将仍然在其内存中具有前一个事务的(成功)查询。
另请参见Connection#close()
javadoc Connection#close()
(重点不是我的):
强烈build议应用程序在调用
close
方法之前显式提交或回滚活动事务。 如果调用close
方法并且存在活动事务,则结果是实现定义的。
closures应该回滚,因为在释放资源时它不会提交,但是最好让error handling是特定的,所以如果你想回滚一个exception,就这样做。 然后你可以在finally {}块中进行清理。 回滚()只发生在错误,在这种情况下你的commit()不成功,甚至没有达到。
Connection conn = null; try { conn = ... ... conn.commit(); } catch (SQLException e) { if (conn != null) { conn.rollback(); } } finally { if (conn != null) { conn.close(); } }