Java数据库交互模式

时间:2014-07-17 22:51:54

标签: java jdbc lambda java-8 try-with-resources

我正在构建一个java应用程序来处理和响应RPC事件。我发现自己一直在做下面的事情,而且我的java知识正在打砖墙。

        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = conn.prepareStatement(removeFollowersStmt);
            preparedStatement.setLong(1, Long.parseLong(conversation) );
            preparedStatement.setLong(2, Long.parseLong(userId) );
            preparedStatement.executeUpdate();

            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        finally
        {
            try {
                assert preparedStatement != null;
                preparedStatement.clearParameters();
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

理想情况下,我只会执行try / catch / finally一次,并且能够在try中调用各种数据库交互。

我不熟悉java这样做但我的想法可能是我可以创建一个函数来接受一个可以在try中调用的闭包吗?

1 个答案:

答案 0 :(得分:1)

我猜这是一个网络应用程序,因为"关注者"。以下内容也适用于独立应用程序,但会有所不同。

您的代码存在两个概念性问题,这会使您的生活更加艰难:

<强> 1。您正试图在错误的地方处理异常。

如果您发现自己编写的代码如下:

try {
    doSomething()
} catch( SomeException e ){
    e.printStackTrace()
}

然后&#34;布局&#34;出现了问题。你的程序。如果将异常处理移动到调用链上的某个位置,您将会好得多。

如果这是一个Web应用程序,请在servlet中执行此操作。所以在你的情况下,这将是:

void executeMyStatements throws SQLException {
    try (PreparedStatement preparedStatement = conn.prepareStatement(removeFollowersStmt))
        preparedStatement.setLong(1, Long.parseLong(conversation) );
        preparedStatement.setLong(2, Long.parseLong(userId) );
        preparedStatement.executeUpdate();
    }
    return true;
}

中的某个地方
MyServlet extends HttpServlet {

    void doGet( ... ){

        try {
             executeMyStatements()
             doSomeMoreStuff()
             executeMyOtherStatements()

        } catch( Throwable t ){

             doSomethingMeaningfullWithException( t );
             // e.g. t.printStackTrace( response.getOutputStream() );
             // logger.error( t ); ...
        }
    }
}

<强> 2。使用交易

(也许你无论如何都要这样做,但万一没有)

交易会帮助你。你是否真的确定如果前一个语句因你捕到的异常失败而继续下一个语句?或者您的数据库处于哪种状态,您可以从哪里开始做您想做的事情?

这非常适合在其他地方处理异常的方法。您基本上想要做的是:( Pseudocode

try{ 
    Connection con = createConnectionSomehow();
    Transaction transaction = con.startTransactionSomehow();

    executeSomeStatements();
    doStuff()
    doDeeperStuffWithMoreStatementsWhichCallOtherStatementsDeepBelowInMoria();

} catch( Exception t ){

    transaction.rollback();
    doSomethingUsefullWith( t );

} finally {

    transactions.commit();
    connection.close()
}

你必须在finally中用if != null包含一些我省略的语句,以便更清楚地显示主要概念,这不应该是难的。

哦,顺便说一下:你在创建陈述时使用parseLong。这个将在某一天失败 NumberFormatExceptionRuntimeException,不需要被捕获。在您的方法中,您只处理SQLException,因此另一个将传播并且(在最坏的情况下在独立应用程序中)将使应用程序崩溃。如果您使用我的方法,catch( Throwable t )将捕获此异常,并将正常处理。

以建议的方式组织代码将使您的生活更轻松,并避免在改进通用代码质量和稳定性时您不喜欢的代码重复。如果出现问题,它将为您提供更好的错误处理。