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

pgx2nnw8  于 2023-03-07  发布在  Spring
关注(0)|答案(4)|浏览(200)

有什么方法可以从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()中获取列类型,第二个是通过运行

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

在第三个方法中,我从目标列类型构建insert语句(prepared),最后使用

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

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

jmp7cifd

jmp7cifd1#

请注意,Spring JDBC模板的要点在于它会在回调方法执行后自动关闭所有资源,包括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
        }
    });
kfgdxczn

kfgdxczn2#

类似这样的方法也能奏效:

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

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

tktrz96b3#

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

xdnvmnnf4#

如果您 * 只是 * 需要ResultSetMetaData,最简单的方法是使用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;
    });

相关问题