Метаданные Resultset из методов Spring JDBCTemplate Query

Есть ли способ получить объект набора результатов из одного из методов запроса jdbctemplate?

У меня есть код как

List<ResultSet> rsList = template.query(finalQuery, new RowMapper<ResultSet>() {
        public ResultSet mapRow(ResultSet rs, int rowNum) throws SQLException {
            return rs;
        }
        }
        );

Я хотел выполнить свой SQL-оператор, хранящийся в finalQuery String, и получить набор результатов. Запрос представляет собой сложное объединение 6-7 таблиц, и я выбрал 4-5 столбцов в каждой таблице и хотел получить метаданные этих столбцов для преобразования типов данных и данных в последующие системы.

Если это простой запрос, и я выбираю только одну таблицу, я могу использовать RowMapper#mapRow и внутри этого метода maprow я могу вызвать ResultsetExtractor.extractData, чтобы получить список результатов; но в этом случае у меня есть сложные объединения в моем запросе, и я пытаюсь получить объект набора результатов и из метаданных этого набора результатов...

Приведенный выше код не годится, потому что для каждого результата он возвращает один и тот же объект набора результатов, и я не хочу хранить их в списке...

Еще раз, если для каждого результата из моего запроса вызывается maprow, JDBCTemplate закроет rs и соединение, даже если в моем списке есть ссылка на объект RS?

Есть ли простой метод, как jdbcTemplate.queryForResultSet(sql)?

Теперь я реализовал свой собственный ResultSet Extractor для обработки и вставки данных в последующие системы.

sourceJdbcTemplate.query(finalQuery, new CustomResultSetProcessor(targetTable, targetJdbcTemplate));

Этот CustomResultSetProcessor реализует ResultSetExtractor, и в методе extractData я вызываю 3 различных метода: 1 - получить форму ColumnTypes rs.getMetaData(), а вторым - получить целевые метаданные get ColumnTypes, выполнив

SELECT NAME, COLTYPE, TBNAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME ='TABLENAME' AND TABCREATOR='TABLE CREATOR'

и в 3-м методе я создаю оператор вставки (подготовленный) из целевых типов столбца и, наконец, вызываю его, используя

new BatchPreparedStatementSetter()
    {
        @Override
        public void setValues(PreparedStatement insertStmt, int i) throws SQLException{} }

Надеюсь, что это помогает другим...

4 ответа

Обратите внимание, что весь смысл Spring JDBC Template заключается в том, что он автоматически закрывает все ресурсы, включая ResultSetпосле выполнения метода обратного вызова. Поэтому было бы лучше извлечь необходимые данные внутри метода обратного вызова и позволить Spring закрыть ResultSet после этого.

Если результат извлечения данных не является List, ты можешь использовать ResultSetExtractor вместо RowMapper:

SomeComplexResult r = template.query(finalQuery, 
    new ResultSetExtractor<SomeComplexResult>() {
        public SomeResult extractData(ResultSet) {
            // do complex processing of ResultSet and return its result as SomeComplexResult
        }
    });

Нечто подобное будет также работать:

Connection con = DataSourceUtils.getConnection(dataSource); // your datasource
Statement s = con.createStatement();

ResultSet rs = s.executeQuery(query); // your query
ResultSetMetaData rsmd = rs.getMetaData();

Хотя я согласен с #axtavt, что ResultSetExtractor является предпочтительным в среде Spring, он действительно заставляет вас выполнить запрос.

Приведенный ниже код не требует от вас этого, поэтому клиентский код не обязан предоставлять фактические аргументы для параметров запроса:

public SomeResult getMetadata(String querySql) throws SQLException {
    Assert.hasText(querySql);

    DataSource ds = jdbcTemplate.getDataSource();
    Connection con = null;
    PreparedStatement ps = null;
    try {
        con = DataSourceUtils.getConnection(ds);
        ps = con.prepareStatement(querySql);
        ResultSetMetaData md = ps.getMetaData();   //<-- the query is compiled, but not executed
        return processMetadata(md);
    } finally {
        JdbcUtils.closeStatement(ps);
        DataSourceUtils.releaseConnection(con, ds);
    }
}

Если вы просто хотите , самый простой способ - использоватьPreparedStatementCallback:

      ResultSetMetaData md = jdbcTemplate.execute(sqlString,
    (PreparedStatementCallback<ResultSetMetaData>) ps -> {
        return ps.getMetaData();
    });

Однако является ли обоснованностьResultSetMetaDataпростирается за конецexecuteвызов сильно различается между SQL-коннекторами; рекомендуется извлечь нужную информацию и вместо этого вернуть ее. Например, чтобы получить список меток столбцов:

      List<String> labels = jdbcTemplate.execute(sqlString,
    (PreparedStatementCallback<List<String>>) ps -> {
        ResultSetMetaData md = ps.getMetaData();
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= md.getColumnCount(); i++) {
            list.add(md.getColumnLabel(i));
        }
        return list;
    });
Другие вопросы по тегам