通用函数不接受自定义RowMapper作为参数 更新1 更新2

问题描述

我已经创建了用于执行jdbctemplate的通用函数

   public <T> execute(String query,Object[] params,Class<T> clazz) {
        try {
            return jdbcTemplate.queryForObject(query,params,clazz);
        } catch (Exception) {
            log.warn("Exception occurred while executing jdbctemplate queryForObject");
        }
    }

上面的代码适用于

execute("SOME QUERY",new Object[] { 12,33 },Integer.class);

但是不适用于自定义RowMapper,例如

 execute("SOME QUERY",new Object[] { 44 },new EmployeRowMapper());

有人可以帮我吗

更新1

当我尝试过

execute("SOME QUERY",EmployeRowMapper.class);

我遇到以下异常

不兼容的类型。必需的Employe,但“执行”被推断为T: 不存在类型变量的实例,因此EmployeRowMapper 符合Employe

EmployeRowMapper一个自定义RowMapper,它返回Employe对象

更新2

我的EmployeRowMapper实现是这样的

@Slf4j
public class EmployeRowMapper implements RowMapper<Employe> {

    @Override
    public Employe mapRow(ResultSet rs,int rowNum) {
        try {
            return Employe.builder()
                    .name(rs.getString("employe_name"))
                    .place(rs.getString("employe_place"))
                    .status(rs.getInt("employe_status")))
                    .age(rs.getInt("employe_age")))
                    .build();
        } catch (Exception exception) {
            log.warn("Exception in getting the request parameter: {}",exception.getMessage());
        }
        return null;
    }
}

解决方法

尝试 execute("SOME QUERY",new Object[] { 44 },EmployeRowMapper.class);

,

您的通用方法execute需要一个Class对象作为参数。调用EmployeRowMapper的构造函数时,您正在传递该实例。

您需要传递EmployeRowMappers类,所以传递EmployeRowMapper.class而不是创建和传递新实例。

更新
因此,我查阅了您正在使用的JdbcTemplate#query的文档。看看。您需要传递应用于创建实体的RowMapper实例。因此,您的execute方法需要将Entity-Type声明为泛型,并期望该类型的RowMapper实例作为参数。像这样:

class DBAccess{
    public <T> T execute(String query,Object[] params,RowMapper<T> mapper){
        return jdbcTemplate.query(query,params,mapper);
    }
}

调用execute时,您需要传递EmployeRowMapper的实例,以便它返回由您传递的Employe构造的RowMapper

注意,根据其文档已弃用了您正在调用的方法。您应该考虑使用其他query方法。

,

queryForObject类中有两个JdbcTemplate方法。一个使用Class,另一个使用RowMapper的实例。现在,由于clazz显然是Class的一个实例,因此将假定它是您要使用的queryForObject的版本。您可以在两种情况下都可以使用此方法,您需要修改方法以检查clazz是否为RowMapper类型:

if (clazz instanceof RowMapper) {
    //cast to RowMapper and use that version of queryForObject
} else {
    //use the one your code currently uses.
}