Spring JDBCTemplate 查询方法的结果集元数据

发布于 2024-10-22 05:24:03 字数 1496 浏览 6 评论 0原文

有什么方法可以从 jdbctemplate 查询方法之一获取结果集对象吗?

我有一个代码,就像

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

我想执行存储在 FinalQuery String 中的 sql 语句并获取结果集。该查询是对 6 到 7 个表的复杂联接,我从每个表中选择 4-5 列,并希望获取这些列的元数据以将数据类型和数据转换为下游系统。

如果这是一个简单的查询,并且我只从一个表中获取,我可以使用 RowMapper#mapRow,在该 maprow 方法中,我可以调用 ResultsetExtractor.extractData 来获取结果列表;但在这种情况下,我的查询中有复杂的连接,我试图获取结果集对象并从该结果集元数据中...

上面的代码不好,因为对于每个结果它将返回相同的结果集对象,并且我不想存储它们在列表中...

再说一次,如果为我的查询的每个结果调用maprow,即使我的列表引用了RS对象,JDBCTemplate也会关闭rs和连接吗?

有没有像 jdbcTemplate.queryForResultSet(sql) 这样的简单方法?

现在我已经实现了自己的 ResultSet Extractor 来处理数据并将其插入到下游系统中。

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

这个 CustomResultSetProcessor 实现了 ResultSetExtractor,在 extractData 方法中我调用 3 个不同的方法,第一个是从 rs.getMetaData() 获取 ColumnTypes,第二个是通过运行

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

和 获取目标元数据的 ColumnTypes在第三种方法中,我正在构建插入语句(准备好的)形式目标列类型,并最终使用

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

希望这对其他人有帮助......

Is there any way I can get resultset object from one of jdbctemplate query methods?

I have a code like

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

I wanted to execute my sql statement stored in finalQuery String and get the resultset. The query is a complex join on 6 to 7 tables and I am select 4-5 columns from each table and wanted to get the metadata of those columns to transform data types and data to downstream systems.

If it is a simple query and I am fetching form only one table I can use RowMapper#mapRow and inside that maprow method i can call ResultsetExtractor.extractData to get list of results; but in this case I have complex joins in my query and I am trying to get resultset Object and from that resultset metadata...

The above code is not good because for each result it will return same resultset object and I dont want to store them in list ...

Once more thing is if maprow is called for each result from my query will JDBCTemplate close the rs and connection even though my list has reference to RS object?

Is there any simple method like jdbcTemplate.queryForResultSet(sql) ?

Now I have implemented my own ResultSet Extractor to process and insert data into downstream systems

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

This CustomResultSetProcessor implements ResultSetExtractor and in extractData method I am calling 3 different methods 1 is get ColumnTypes form rs.getMetaData() and second is getColumnTypes of target metadata by running

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

and in 3rd method I am building the insert statement (prepared) form target columntypes and finally calling that using

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

Hope this helps to others...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧伤还要旧人安 2024-10-29 05:24:03

请注意,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
        }
    });

Note that the whole point of Spring JDBC Template is that it automatically closes all resources, including ResultSet, after execution of callback method. Therefore it would be better to extract necessary data inside a callback method and allow Spring to close the ResultSet after it.

If result of data extraction is not a List, you can use ResultSetExtractor instead of RowMapper:

SomeComplexResult r = template.query(finalQuery, 
    new ResultSetExtractor<SomeComplexResult>() {
        public SomeResult extractData(ResultSet) {
            // do complex processing of ResultSet and return its result as SomeComplexResult
        }
    });
放手` 2024-10-29 05:24:03

像这样的东西也可以工作:

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

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

Something like this would also work:

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

ResultSet rs = s.executeQuery(query); // your query
ResultSetMetaData rsmd = rs.getMetaData();
冷月断魂刀 2024-10-29 05:24:03

虽然我同意 #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);
    }
}

Although I agree with #axtavt that ResultSetExtractor is preferred in Spring environment, it does force you to execute the query.

The code below does not require you to do so, so that the client code is not required to provide the actual arguments for the query parameters:

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);
    }
}
忘年祭陌 2024-10-29 05:24:03

如果您只是想要ResultSetMetaData,最简单的方法是使用PreparedStatementCallback

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

但是,ResultSetMetaData的有效性是否有效code> 超出了 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;
    });

If you just want the ResultSetMetaData, the easiest way is to use a PreparedStatementCallback:

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

However, whether the validity of the ResultSetMetaData extends past the end of the execute call is tremendously variable between SQL connectors; it's advised to extract the information you want and return that instead. For example, to get the list of column labels:

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;
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文