首页 > 解决方案 > JDBCTemplate 执行查询后关闭准备好的语句

问题描述

我想在完成数据库查询后关闭我的连接。问题是我正在使用准备好的语句,因为它们是预编译的,所以更安全。我想关闭数据库连接,以便以后可以将其重用于另一个查询。

该文档说明了以下内容:

/**
 * Create a statement in this connection. Allows implementations to use
 * PreparedStatements. The JdbcTemplate will close the created statement.
 * @param con the connection used to create statement
 * @return a prepared statement
 * @throws SQLException there is no need to catch SQLExceptions
 * that may be thrown in the implementation of this method.
 * The JdbcTemplate class will handle them.
 */
PreparedStatement createPreparedStatement(Connection con) throws SQLException;

我遇到了池中没有可用连接的情况。

我有以下内容,但它抛出一个异常,说在语句关闭后不允许任何操作。

private IRespondent InsertRespondentToken(IRespondent respondent) {
try{
    final String insertRespondent = "insert into respondents_token (SynchroID,TerminalID,QuestionnaireID,ProjectID,Token) values (?,?,?,?,?)";

    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(
            (Connection con) -> {
                try{
                    PreparedStatement pst = con.prepareStatement(insertRespondent, new String[] {"ID"});
                    pst.setInt(1, respondent.getSynchroId());
                    pst.setInt(2, respondent.getTerminalId());

                    pst.setInt(3, respondent.getQuestionnaireId());

                    pst.setInt(4,respondent.getProjectId());

                    respondent.setToken(GenerateUniqueId.getIdentifier());

                    pst.setString(5,respondent.getToken());

                    return pst;
                }
                catch (SQLException e)
                {
                    log.error("Prepared statement failed! Read the stack!",e);
                }
                finally {
                    con.close(); // IS thsi right. Or there is another way of doing it.
                }
                return null;
            }
            ,keyHolder);
    }catch(NullPointerException ex){
        log.error("Error during end element parsing.", ex);
        if (respondent.getId() != -1)
            deleteRespondent(respondent.getId());
        return null;
    }

  return respondent;
 }

标签: javadatabasespring-bootjdbc

解决方案


您正在关闭连接,并通过扩展您创建的准备好的语句。所以当 JdbcTemplate 继续执行语句时,连接(和语句)已经关闭。您需要删除try-catch-finally关闭连接的代码周围(并吞下任何异常)。

另请参阅 Spring 文档中的示例,检索自动生成的密钥部分。您需要做的就是准备语句并填充其参数。

另一种看待这一点的方式是使用资源管理的基本“规则”:您只关闭您创建的内容(除非另有说明)。在这种情况下,您没有创建连接,因此您不负责关闭它。


推荐阅读