0

I usually do this in my repository package:

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

I wish to remove boilerplate in second method so I've switched to executeObject(). I tried this. Both failed.

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

Problem is that my device is null. I tried also declaring just Object instead of Device or List and it's still null. What am I doing wrong?

I know that result is correctly mapped into Device class because I see that procGetDeviceDetails (SimpleJdbcCall) has declaredRowParameters equal to {#result-set-1=org.springframework.jdbc.core.BeanPropertyRowMapper@79095fd7} and BeanPropertyRowMapper has mappedClass set to Device.

Seems that generics or something else troubles me. I found example here. https://jira.spring.io/browse/SPR-7270

Thanks!

1 Answer 1

1

The problem was with stored procedure design. These methods in SimpleJdbcCall uses OUTPUT parameters while my stored procedures returns data normally as result set.

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

Because of this I've created subclass of SimpleJdbcCall with two additional methods executeObjectSingle and executeObjectList which enables me simple usage.

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

Of course this should be extended with size and null checking, but it shows the idea.

Stored procedure example in 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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.