Метаданные 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;
});