从 JDBCTemplate 获取语句

Get Statement from JDBCTemplate

我有这个代码,

SimpleJdbcCall sql = new SimpleJdbcCall(dataSource).withProcedureName(procName);
sql.execute(parameters);

而且我相信这在幕后使用了 JDBC 语句。我怎样才能从这里到达那个物体? (我需要在语句中调用 .getWarnings() 方法)。

换句话说,我如何获得 SQLWarnings AND 命名参数?

您或许应该直接使用 JdbcTemplate,或者将其子类化以用于您的 SimpleJdbcCall(而不是 DataSource)。 JdbcTemplate 有一个方法 execute(CallableStatementCreator, CallableStatementCallback),其中可以传递回调以获取使用的 Statement 对象。

您可以重写该方法并将传递的回调包装在一个自己的回调中,该回调存储语句供以后使用。

public class CustomJdbcTemplate extends JdbcTemplate {

    private CallableStatement lastStatement;

    public CustomJdbcTemplate(DataSource dataSource) {
        super(dataSource);
    }

    public CallableStatement getLastStatement() {
        return lastStatement;
    }

    @Override
    public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) throws DataAccessException {
        StoringCallableStatementCallback<T> callback = new StoringCallableStatementCallback<T>(action); 
        try {
            return super.execute(csc, callback);
        }
        finally {
            this.lastStatement = callback.statement;
        }
    }

    private static class StoringCallableStatementCallback<T> implements CallableStatementCallback<T> {

        private CallableStatementCallback<T> delegate;

        private CallableStatement statement;

        private StoringCallableStatementCallback(CallableStatementCallback<T> delegate) {
            this.delegate = delegate;
        }

        @Override
        public T doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
            this.statement = cs;
            return delegate.doInCallableStatement(cs);
        }

    }

}

请注意,当您稍后检索该语句时,它很可能会被关闭,因此 getWarnings() 可能会导致错误,具体取决于使用的 JDBC 驱动程序。所以也许您应该存储警告而不是语句本身。

这需要大量的挖掘,但这里是您如何获得 SQLWarnings(或 Print 语句)A​​ND 命名参数的方法。我扩展了 JdbcTemplate 并覆盖了 handleWarnings() 方法,然后将其传递到我的 SimpleJdbcCall 中。

  public class JdbcTemplateLoggable extends JdbcTemplate{


    List<String> warnings;

    public JdbcTemplateLoggable(DataSource dataSource){
        super(dataSource);
        warnings = new ArrayList<String>();
    }

    protected void handleWarnings(Statement stmt){
        try {
            SQLWarning warning = stmt.getWarnings();
            while(warning != null){
                warnings.add(warning.getMessage());
                warning = warning.getNextWarning();
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public List<String> getWarnings(){
        return warnings;
    }
}

然后在我的主程序中

JdbcTemplateLoggable template = new JdbcTemplateLoggable(dataSource);
        SimpleJdbcCall sql = new SimpleJdbcCall(template).withProcedureName(procName);
        sql.execute(parameters);
        for(String s : template.getWarnings()){
            log.info(s);
        }