栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用新的try-with-resources块对SQLException进行事务回滚

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用新的try-with-resources块对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-catch。

编辑(2018)

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

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

public class Foo {    interface ConnectionProvider {        Connection get() throws SQLException;    }    public static <A> A doInTransation(ConnectionProvider connectionProvider, Function<Connection, A> 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。因此,如果在池中为假,则不应触摸它。

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



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/497494.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号