【问题标题】:Resultset Metadata from Spring JDBCTemplate Query methods来自 Spring JDBCTemplate 查询方法的结果集元数据
【发布时间】:2023-03-11 20:34:01
【问题描述】:

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

我有一个类似的代码

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

我想执行存储在 finalQuery 字符串中的 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 种不同的方法 1 是从 rs.getMetaData() 中获取 ColumnTypes,其次是通过运行获取目标元数据的列类型

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

在第三种方法中,我正在构建插入语句(准备好的)表单目标列类型,并最终使用

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

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

【问题讨论】:

    标签: spring metadata resultset jdbctemplate


    【解决方案1】:

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

    【讨论】:

    • 在我的例子中,finalQuery 每次都是动态的,我需要执行 26 个这样的复杂查询。因此,我无法将所有查询结果映射到 SomeComplexResult 以将其返回。我可以在 extractData 中映射和转换数据和数据类型,但是一旦我提取了,我需要将其插入到下游系统的其他目标数据库中。我想上面的解决方案对我不起作用。
    • 如果我喜欢下面是一个好主意code try{ con = jdbcTempalte.getDataSource().getConnection(); con.createStatement(); rs = st.executeQuery(finalQuery); rsmd = rs.getMetadata(); code我不知道我是否获得连接表单模板并获得我想要的东西并关闭资源,不确定这是否是一个好主意......请帮助
    • @sanumala:关键是你不需要返回任何东西——你可以在回调方法中实现需要访问ResultSet的逻辑。
    • @axtavt 是否可以返回Map&lt;String,List&lt;Objects&gt;&gt;。我的Question here
    • 如果我想处理表中的所有条目但我的表不能包含 20+ 百万行怎么办。这种情况下怎么办?我使用spring JdbcTempate
    【解决方案2】:

    类似的方法也可以:

    Connection con = DataSourceUtils.getConnection(dataSource); // your datasource
    Statement s = con.createStatement();
    
    ResultSet rs = s.executeQuery(query); // your query
    ResultSetMetaData rsmd = rs.getMetaData();
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-18
        • 1970-01-01
        • 1970-01-01
        • 2019-04-11
        • 2021-02-20
        • 1970-01-01
        • 2010-11-27
        • 2013-04-15
        相关资源
        最近更新 更多