How exactly work the Spring RowMapper interface?

后端 未结 2 1264
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-31 21:57

I am studying for the Spring Core certification and I have some doubts about how Spring handle the JDBC queries:

So I know that I can obtain data from my DB tables i

相关标签:
2条回答
  • 2020-12-31 22:24

    The queryForObject method looks like this:

    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1));
        return DataAccessUtils.requiredSingleResult(results);
    }
    

    The queryForObject-method internally invokes the method query on the JdbcTemplate object. The query-method is defined as:

    public <T> T query(
            PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
            throws DataAccessException;
    

    As you can see, a ResultSetExtractor<T> is passed to the query-method and Spring conveniently converts your RowMapper<T> to an object of type new RowMapperResultSetExtractor<T>(rowMapper, 1). The RowMapperResultSetExtractor is the object that holds the key to the magic. When the object is invoked it iterates all rows as per this snippet:

    public List<T> extractData(ResultSet rs) throws SQLException {
        List<T> results = (this.rowsExpected > 0 ? new ArrayList<T>(this.rowsExpected) : new ArrayList<T>());
        int rowNum = 0;
        while (rs.next()) {
            results.add(this.rowMapper.mapRow(rs, rowNum++));
        }
        return results;
    }
    

    So, your original RowMapper is the callback that is called for each row. Furthermore, as you can see here your RowMapper is invoked for all matching results and the Restaurant-object that you created is added to the result list. However, since you query for only one object the following statement is finally used to return your single Restaurant object.

            return DataAccessUtils.requiredSingleResult(results);
    

    So, to sum up: JdbcTempalte implementes the Strategy Pattern (which is similar to the Template method pattern). And by providing a Strategy interface (the RowMapper) you can let JdbcTemplate do the heavy lifting for you (handling exceptions, connections etc). The RowMapper maps each hit as a POJO (the Restaurant) and all hits are collected to a List. The method queryForObject then takes the first row from that List and returns it to the caller. The return value is based on the generic type of the RowMapper which in your case is Restaurant.

    0 讨论(0)
  • 2020-12-31 22:37

    Use jdbcTemplate.queryForObject it will resolve your problem like this

    public YourPojo getDatabaseDetails(int masterId) {
    
        sql = "Select * FROM <table_name> where ID=?";
        YourPojo pojo = (YourPojo) jdbcTemplate.queryForObject(sql,
                new Object[] { masterId }, new RowMapper<YourPojo>() {
                    @Override
                    public <YourPojo> mapRow(ResultSet rs, int rowNum)
                            throws SQLException {
                        YourPojo pojo2 = new YourPojo();
                        pojo2.setAccountId(rs.getString("AccountId"));
                        pojo2.setAccountName(rs.getString("AccountName"));
                        pojo2.setAccountCRN(rs.getString("AccountCRN"));
                        pojo2.setAccountStatus(rs.getString("AccountStatus"));
                        return pojo2;
                    }
                });
        return pojo;
    }
    
    0 讨论(0)
提交回复
热议问题