【问题标题】:Java 1.6 java.sql try/catch/finally crazy codingJava 1.6 java.sql try/catch/finally 疯狂编码
【发布时间】:2012-03-19 03:49:08
【问题描述】:

我目前正在创建许多将使用连接池访问数据库的类。 所以我得到一个连接,创建一个语句并得到结果集。 (我不能使用 Java 1.7 和出色的自动资源管理) 在完成我的方法时,我必须以 finally 块结束:

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close result set", sqle);
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close statement", sqle);
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close connection", sqle);
            }
        }

我已经看到 XX 类每个有 4/5 个方法的噩梦了。

创建一个帮助类对每个对象类型都有一个特殊的关闭方法是否是一种好习惯,例如:

public static void closeResource(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException sqle) {
                logger.error("Couldn't close connection", sqle);
            }
        }

然后就照常使用finallyxx.close(connection);xx.close(statement);xx.close(rs);

或者以同样的想法(我知道在这一点上我会震惊一些人,因为我自己觉得这有点不合时宜),有一个像public static void closeResources(Object... obj) {} 这样的方法和一个糟糕的instanceof 列表?

或者根据您的经验,在任何地方编码整个事情会更好?

【问题讨论】:

  • 也许看看使用方面。您可能会使用 aspectJ 编织此功能。
  • @TomaszNurkiewicz 感谢您向我介绍 Spring JDBC,我不会为这个项目使用它,但我会记住这一点。

标签: java try-catch


【解决方案1】:

使用 Apache 公共项目:http://commons.apache.org/dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html

DbUtils.closeQuietly() 可能是你需要的

【讨论】:

  • 正是我要做的。感谢您指向库。我前一阵子用过,完全忘记了那些实用程序
【解决方案2】:

使用重载。

private void close(ResultSet rSet) throws SQLException {
    if (rSet != null) {
        rSet.close();
    }
}

private void close(Statement statement) throws SQLException {
    if (statement != null) {
        statement.close();
    }
}

private void close(Connection conn) throws SQLException {
    if (conn != null) {
        conn.close();
    }
}

现在使用会更干净:

try {
    // do db stuff
} catch (Exception e) {
    logger.error("log it", e);
} finally {
    close(rs);
    close(cs);
    close(conn);
}

【讨论】:

  • 是的,如果我继续使用方法,我正在考虑这一点。还是谢谢
【解决方案3】:

再举一个例子。适用于简单的小型项目。

Object doRequest() throws SQLException {

    PreparedStatement ps = ... // initialize statement
    try {
        ResultSet rs = ps.executeQuery();
        try {

           // use ResultSet
           return someResult;

        } finally {
           rs.close();
        } 
    } finally {
        ps.close();
    }

}

虽然它不是假装是完整的解决方案(很多嵌套的try-finally 非常难以阅读),但有几个优点:

  • 方法本身不处理异常处理。通常只有调用者可以决定如何处理异常。
  • 如下,方法总是返回正确的结果抛出异常。不需要神奇的“错误值”。
  • 资源仅在初始化时才关闭。无需检查null berode close()

【讨论】:

    【解决方案4】:

    您还可以利用close 方法没有参数这一事实,即对于您要关闭的每个类,并创建一个反射辅助方法,如下所示:

        public static final void tryClose(Object o){
            if(o != null){
                Method[] m = o.getClass().getMethods();
                for (Method method : m) {
                    if("close".equals(method.getName())){
                        if(!method.isAccessible()) method.setAccessible(true);
                        try {
                            method.invoke(o);
                        } catch (Exception e) {
                            System.err.println(e);
                        }
                        break;
                    }
                }
            }       
        }
    

    编辑:用 FileWriter 测试,在我的机器上运行良好。

    【讨论】:

    • 这对我的期望来说有点过分了;)。不过还是谢谢分享。
    猜你喜欢
    • 2011-10-31
    • 2011-11-17
    • 2011-06-01
    • 2015-09-05
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    相关资源
    最近更新 更多