java 事务处理 try catch_java-使用新的try-with-resources b在SQLException上进行事务回滚...

根据语言规范,将在执行catch子句之前关闭连接([http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3.2 )。

一种可能的解决方案是嵌套try-with-resources语句:

try (java.sql.Connection con = createConnection())

{

con.setAutoCommit(false);

try (Statement stm = con.createStatement())

{

stm.execute(someQuery); // causes SQLException

}

catch(SQLException ex)

{

con.rollback();

con.setAutoCommit(true);

throw ex;

}

con.commit();

con.setAutoCommit(true);

}

希望可以说明这一点。 如果您计划在生产代码中使用它,则应该对其进行很多改进。

例如,如果您使用的是连接池,则必须在获得连接时返回它,因此con.setAutoCommit(true); 应该在finally子句中完成。 这意味着外部的try-with-resources应该是传统的try-catch-finally。

编辑(2018)

我仍然看到有人对此发表评论,所以我想给它2018年的答复。 我不再使用Java,主要是使用Scala,Clojure和Kotlin,并且此代码尚未经过测试,因此请仅将其作为另一个示例。 但是,由于Java具有lambda,因此我认为以下方法要好得多。 我在其他语言的生产代码中也做了类似的事情。

在这种方法中,有一个inTransaction函数可以处理所有令人讨厌的事务。 但是用法很简单。

public class Foo {

interface ConnectionProvider {

Connection get() throws SQLException;

}

public static A doInTransation(ConnectionProvider connectionProvider, Function f) throws SQLException {

Connection connection = null;

A returnValue;

boolean initialAutocommit = false;

try {

connection = connectionProvider.get();

initialAutocommit = connection.getAutoCommit();

connection.setAutoCommit(false);

returnValue = f.apply(connection);

connection.commit();

return returnValue;

} catch (Throwable throwable) {

// You may not want to handle all throwables, but you should with most, e.g.

// Scala has examples: https://github.com/scala/scala/blob/v2.9.3/src/library/scala/util/control/NonFatal.scala#L1

if (connection != null) {

connection.rollback();

}

throw throwable;

} finally {

if (connection != null) {

try {

if(initialAutocommit){

connection.setAutoCommit(true);

}

connection.close();

} catch (Throwable e) {

// Use your own logger here. And again, maybe not catch throwable,

// but then again, you should never throw from a finally ;)

StringWriter out = new StringWriter();

e.printStackTrace(new PrintWriter(out));

System.err.println("Could not close connection " + out.toString());

}

}

}

}

public static void main(String[] args) throws SQLException {

DataSource ds = null;

// Usage example:

doInTransation(ds::getConnection, (Connection c) -> {

// Do whatever you want in a transaction

return 1;

});

}

}

我希望有一些经过战斗验证的库可以为您做这些事情,至少在其他语言中也是如此。

我看到关于自动提交和连接池的一些评论。 上面的示例应该不知道连接来自何处,是否是一个池,即仅在它是初始值时才将其设置回true。 因此,如果从池中获取它是错误的,则不应触摸它。

关于尝试资源的最终决定。 我认为这不是一个很好的抽象,因此在更复杂的场景中使用它时要格外小心。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值