使用SpringJdbc时出现Lock时,PreparateStatement执行停止

时间:2016-02-23 10:56:22

标签: java locking spring-jdbc

在客户端环境中,我们面临一个Lock on table。 为了重现,我们在我们当地的环境中手动锁定表。

我们需要创建继续执行的块代码,并且在发生此锁定时不会停止。 但是使用SpringJdbc它会停止执行。

这是我正确执行但未停止的代码: 在我们的代码OracleRepositoryJdbcTemplateImpl。

@Override
public int[] update(final String sql, final BatchPreparedStatementSetter pss,
               final String queryName) throws DataAccessException {
   long start = executionStart();
   try {
      return execute(sql, new PreparedStatementCallback<int[]>() {
                  @Override
                  public int[] doInPreparedStatement ( final PreparedStatement ps)throws SQLException {
                  ... Code that are correctly executed
                  logger.warn("********** SQLException");
                  return int[1];


               }
            }
      );
   } finally {
      System.out.println("********** Finally of the update method");
      queryStop(start, queryName);
   }
}

和org.springframework.jdbc.core.JdbcTemplate:

public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
      throws DataAccessException {

   Assert.notNull(psc, "PreparedStatementCreator must not be null");
   Assert.notNull(action, "Callback object must not be null");
   if (logger.isDebugEnabled()) {
      String sql = getSql(psc);
      logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
   }

   Connection con = DataSourceUtils.getConnection(getDataSource());
   PreparedStatement ps = null;
   try {
      Connection conToUse = con;
      if (this.nativeJdbcExtractor != null &&
            this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
         conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
      }
      ps = psc.createPreparedStatement(conToUse);
      applyStatementSettings(ps);
      PreparedStatement psToUse = ps;
      if (this.nativeJdbcExtractor != null) {
         psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
      }
      T result = action.doInPreparedStatement(psToUse); // HERE
      handleWarnings(ps);
      return result;
   }
   catch (SQLException ex) {
      // Release Connection early, to avoid potential connection pool deadlock
      // in the case when the exception translator hasn't been initialized yet.
      if (psc instanceof ParameterDisposer) {
         ((ParameterDisposer) psc).cleanupParameters();
      }
      String sql = getSql(psc);
      psc = null;
      JdbcUtils.closeStatement(ps);
      ps = null;
      DataSourceUtils.releaseConnection(con, getDataSource());
      con = null;
      throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex);
   }
   finally {
      if (psc instanceof ParameterDisposer) {
         ((ParameterDisposer) psc).cleanupParameters();
      }
      JdbcUtils.closeStatement(ps);
      DataSourceUtils.releaseConnection(con, getDataSource());
   }
}

public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException {
   return execute(new SimplePreparedStatementCreator(sql), action);
}

这是在这个评论行中的块执行。 显示日志********** SQLException,但执行永远不会进入我们的finally块。 来自JdbcTemplate的'con'和'ps'对象显示“收集数据......”。

你知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

为了修复它,我们将代码执行嵌套在Callable函数中:

@Override
public int[] update(final String sql, final BatchPreparedStatementSetter pss, final String queryName) throws DataAccessException {
    Callable<int[]> call = new Callable<int[]>(){
         @Override
         public int[] call() throws Exception{
              return updateInCallable(sql, pss, queryName)    
         }
         public int[] updateInCallable(final String sql, final BatchPreparedStatementSetter pss, final String queryName) throws DataAccessException {
         // Our code
         }
    }             
}