Embracing the Messiness in Search of Epic Solutions

Spring: Invoking Stored Procedure

Posted

in

PROBLEM

There are many ways to skin a cat… so is invoking a stored procedure using Spring.

Let’s assume we want to invoke the following stored procedure that accepts 3 arguments (person ID, start date, end date):-

{ call calendar_sp (?, ?, ?) }

This stored procedure returns a result set where each row contains a person ID, a date and a description.

SOLUTION

Create a class that extends org.springframework.jdbc.object.StoredProcedure:-

@Component
public class CalendarStoredProcedure extends StoredProcedure {</code>
<code>

    @Autowired
    public CalendarStoredProcedure(DataSource dataSource) {
        super(dataSource, "calendar_sp");

        // input parameters
        declareParameter(new SqlParameter("person_id", Types.INTEGER));
        declareParameter(new SqlParameter("start_date", Types.VARCHAR));
        declareParameter(new SqlParameter("end_date", Types.VARCHAR));

        // handling result set
        declareParameter(new SqlReturnResultSet("calendarDays", new RowMapper<CalendarDayBean>() {
            @Override
            public CalendarDayBean mapRow(ResultSet rs, int i) throws SQLException {
                return new CalendarDayBeanBuilder()
                        .setPersonId(rs.getLong("person_id"))
                        .setDate(CommonUtils.convertSQLDateToLocalDate(rs.getDate("calendar_date")))
                        .setDescription(rs.getString("description"))
                        .createCalendarDayBean();
            }
        }));

        compile();
    }

    @SuppressWarnings("unchecked")
    public Collection<CalendarDayBean> getCalendar(Long personId, LocalDate startDate, LocalDate endDate) {
        final String strStartDate = ...; // convert `startDate` to string
        final String strEndDate = ...; // convert `endDate` to string

        final Map<String, Object> results = execute(personId, strStartDate, strEndDate);
</code>
<code>        return ImmutableList.copyOf((List<CalendarDayBean>) results.get("calendarDays"));
    }
}

The data source is wired into this spring-managed bean. A helper API called getCalendar(...) is created to allow the DAO to invoke this stored procedure.

Now, create a DAO class and wire the stored procedure class into it:-

@Service
public class CalendarDAO {
    private final CalendarStoredProcedure calendarStoredProcedure;</code>
<code>

    @Autowired
    public CalendarDAO(CalendarStoredProcedure calendarStoredProcedure) {
        this.calendarStoredProcedure = calendarStoredProcedure;
    }

    @Override
    public Collection<CalendarDayBean> getCalendar(final Long personId,
                                                   final LocalDate startDate,
                                                   final LocalDate endDate) {
</code>
<code>        return calendarStoredProcedure.getCalendar(personId, startDate, endDate);
    }
}

Comments

Leave a Reply