Java Spring RowMapper接口究竟是如何工作的?

Java Spring RowMapper接口究竟是如何工作的?,java,spring,spring-jdbc,jdbctemplate,Java,Spring,Spring Jdbc,Jdbctemplate,我正在学习Spring核心认证,我对Spring如何处理JDBC查询有一些疑问: 因此,我知道我可以通过各种方式从数据库表中获取数据,具体取决于我希望获取的数据类型: 1) 查询简单类型(作为int、long或字符串):我使用jdbcTemplate类的queryForObject()方法,类似于: String sql = "SELECT count(*) FROM T_REWARD"; int rowsNumber = jdbcTemplate.queryForObject(sql, Int

我正在学习Spring核心认证,我对Spring如何处理JDBC查询有一些疑问:

因此,我知道我可以通过各种方式从数据库表中获取数据,具体取决于我希望获取的数据类型:

1) 查询简单类型(作为int、long或字符串):我使用jdbcTemplate类的queryForObject()方法,类似于:

String sql = "SELECT count(*) FROM T_REWARD";
int rowsNumber = jdbcTemplate.queryForObject(sql, Integer.class);
String sql = “select * from PERSON”;
return jdbcTemplate.queryForList(sql);
因此,为了获得一个简单对象作为int值,我使用queryForObject()方法将sql语句和我期望从该方法的输出中接收的对象类型传递给它

好的,这很简单,我认为这很好

2) 查询放入映射对象中的整个表行:因此,如果我不需要单个值(可以放入表中特定行的单个列或类似前一示例的内容),我可以使用queryForMap(…)queryForList()方法,方法如下:

2.1)queryForMap():如果希望将单行放入单个映射对象中,其中每个列的值映射到我的映射中,我会使用它,例如:

String sql = "select * from T_REWARD where CONFIRMATION_NUMBER = ?";
Map<String, Object> values = jdbcTemplate.queryForMap(sql,confirmation.getConfirmationNumber());
我想这也很清楚

然后我可以使用JdbcTemplate将结果集映射到域对象,这对我来说并不清楚

阅读文档时会被告知JdbcTemplate使用回调方法支持这一点。这种回调方法的确切含义是什么

我知道Spring提供了一个行映射器接口,用于将结果集的一行映射到一个对象

public interface RowMapper<T> {
    T mapRow(ResultSet rs, int rowNum)
    throws SQLException;
}
class RestaurantRowMapper implements RowMapper<Restaurant> {
    public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
        return mapRestaurant(rs);
    }
}
return jdbcTemplate.queryForObject(sql, new RestaurantRowMapper(), merchantNumber);
而这个内部类

public interface RowMapper<T> {
    T mapRow(ResultSet rs, int rowNum)
    throws SQLException;
}
class RestaurantRowMapper implements RowMapper<Restaurant> {
    public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
        return mapRestaurant(rs);
    }
}
return jdbcTemplate.queryForObject(sql, new RestaurantRowMapper(), merchantNumber);
所以我很难理解这些东西到底是如何工作的

我的主要疑问是:我知道,使用queryForObject()方法,我将预期作为输出的对象类型作为输入参数传递给它(例如整数或长整数)

如果我希望获得一个表示整个表行的域对象(例如映射到Restaurand对象的餐厅表的一行),我认为应该使用这个对象(作为餐厅对象)但在上一个示例中,我使用**行映射器对象,而不是域对象

public interface RowMapper<T> {
    T mapRow(ResultSet rs, int rowNum)
    throws SQLException;
}
class RestaurantRowMapper implements RowMapper<Restaurant> {
    public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
        return mapRestaurant(rs);
    }
}
return jdbcTemplate.queryForObject(sql, new RestaurantRowMapper(), merchantNumber);
此内部类仅包含返回预期的域对象的mapRow()方法

class RestaurantRowMapper implements RowMapper<Restaurant> {
    public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
        return mapRestaurant(rs);
    }
}
类RestaurantRowMapper实现行映射器{
公共餐厅mapRow(结果集rs,int i)引发SQLException{
返回餐厅(rs);
}
}
因此,我认为Spring会自动调用mapRow()方法,该方法返回Restaurand域对象,该对象会自动替换为queryForObject()方法,或者类似的方法。但我不太确定它是否确实有效

我错过了什么?你能解释一下后台到底发生了什么吗


Tnx

查询对象的方法如下所示:

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);
}
如您所见,一个
ResultSetExtractor
被传递到
query
-方法,Spring可以方便地将
RowMapper
转换为
new RowMapperResultSetExtractor(RowMapper,1)
类型的对象。
RowMapperResultSetExtractor
是持有魔法钥匙的对象。调用该对象时,它会按照以下代码段迭代所有行:

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

总之:
JdbcTempalte
实现了(类似于)。通过提供一个策略接口(行映射器
RowMapper
),您可以让
JdbcTemplate
为您完成繁重的工作(处理异常、连接等)。
行映射器
将每个点击映射为POJO(餐厅),所有点击都收集到一个
列表
。方法
queryForObject
然后从
列表中获取第一行,并将其返回给调用者。返回值基于
行映射器的泛型类型,在您的情况下,它是
餐厅

使用jdbcTemplate.queryForObject它将像这样解决您的问题

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;
}
public YourPojo getDatabaseDetails(int masterId){
sql=“选择*从其中ID=?”;
YourPojo pojo=(YourPojo)jdbcTemplate.queryForObject(sql,
新对象[]{masterId},新的行映射器(){
@凌驾
公共映射行(结果集rs,int rowNum)
抛出SQLException{
YourPojo pojo2=新的YourPojo();
pojo2.setAccountId(rs.getString(“AccountId”);
pojo2.setAccountName(rs.getString(“AccountName”);
pojo2.setAccountCRN(rs.getString(“AccountCRN”);
pojo2.setAccountStatus(rs.getString(“AccountStatus”);
返回pojo2;
}
});
返回pojo;
}