Resultset Metadata from Spring JDBCTemplate Query methods

22,851

Solution 1

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
        }
    });

Solution 2

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();

Solution 3

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);
    }
}
Share:
22,851
sanumala
Author by

sanumala

Working on java technologies

Updated on July 06, 2020

Comments

  • sanumala
    sanumala almost 4 years

    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...