Spring Framework中的SimpleJdbcCall executeObject()用法

时间:2015-07-08 14:52:28

标签: spring spring-mvc spring-data spring-jdbc

我通常在我的存储库包中执行此操作:

public void setDataSource(DataSource dataSource) {
    procGetDeviceDetails = new SimpleJdbcCall(dataSource)
        .withProcedureName("web_Device_Details")
        .returningResultSet("results", BeanPropertyRowMapper.newInstance(Device.class));
}

public Device deviceDetails(Map input) {
    Map m = procGetDeviceDetails.execute(input);
    List<Device> list = (List<Device>) m.get("results");
    if (list.size() > 0) {
        return list.get(0);
    }
    return null;
}

我希望在第二种方法中删除样板,以便我切换到executeObject()。我试过这个。都失败了。

public Device deviceDetails(Map input) {
    Device device = procGetDeviceDetails.executeObject(Device.class, input);
    return device;
}

public Device deviceDetails(Map input) {
    List<Device> device = procGetDeviceDetails.executeObject(List.class, input);
    return device.get(0);
}

问题是我的设备为空。我还尝试声明Object而不是Device或List,它仍然是null。我做错了什么?

我知道结果已正确映射到Device类,因为我看到procGetDeviceDetails(SimpleJdbcCall)已将declaredRowParameters等于{#result-set-1=org.springframework.jdbc.core.BeanPropertyRowMapper@79095fd7}并且BeanPropertyRowMapper已设置mappedClass到设备。

似乎泛型或其他东西让我烦恼。我在这里找到了例子。 https://jira.spring.io/browse/SPR-7270

谢谢!

1 个答案:

答案 0 :(得分:1)

问题在于存储过程设计。 SimpleJdbcCall中的这些方法使用OUTPUT参数,而我的存储过程通常以结果集的形式返回数据。

@Override
@SuppressWarnings("unchecked")
public <T> T executeObject(Class<T> returnType, Map<String, ?> args) {
    return (T) doExecute(args).get(getScalarOutParameterName());
}

因此我创建了SimpleJdbcCall的子类,使用了另外两个方法executeObjectSingle和executeObjectList,这使我可以简单使用。

public <T> T executeObjectSingle(Class<T> returnType, Map<String, ?> args) {
    List<T> o = executeObjectList(returnType, args);
    return o.get(0);
}

public <T> List<T> executeObjectList(Class<T> returnType, Map<String, ?> args) {
    Map<String, Object> m = doExecute(args);
    List<T> o = (List<T>) m.get(parameterNameResultSet);
    return o;
}

当然,这应该通过大小和空检查来扩展,但它显示了这个想法。

SQL Server中的存储过程示例:

ALTER PROCEDURE [dbo].[Device_something]
    @device varchar(50),
    @username varchar(50),
    @password varchar(50)
AS
BEGIN
    SET NOCOUNT ON;

    select 'foo' as token
    union
    select 'bar' as token
END