我通常在我的存储库包中执行此操作:
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
谢谢!
答案 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