Spring Сохраненная процедура - результаты, возвращаемые из процедуры, всегда пусты
Я использую классы Spring JdbcTemplate и StoredProcedure. У меня возникла проблема с тем, чтобы класс хранимой процедуры работал у меня.
У меня есть хранимая процедура в базе данных оракула. Его подпись
CREATE OR REPLACE PROCEDURE PRC_GET_USERS_BY_SECTION
(user_cursor OUT Pkg_Types.cursor_type
, section_option_in IN Varchar2
, section_in IN Varchar2) AS ....
где
TYPE cursor_type IS REF CURSOR;
Я создал следующий класс хранимой процедуры для получения информации из процедуры оракула
private class MyStoredProcedure extends StoredProcedure
{
public MyStoredProcedure(JdbcTemplate argJdbcTemplate)
{
super(argJdbcTemplate, "PRC_GET_USERS_BY_SECTION");
declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR));
declareParameter(new SqlParameter("input1", Types.VARCHAR));
declareParameter(new SqlParameter("input2", Types.VARCHAR));
compile();
}
public Map<String, Object> execute() {
Map<String, Object> inParams = new HashMap<String, Object>();
inParams.put("input1", "BG");
inParams.put("input2", "FE");
Map output = execute(inParams);
return output;
}
}
Я вызываю это в методе в одном из моих классов DAO
public List<String> getUserListFromProcedure() throws BatchManagerException
{
MyStoredProcedure sp = new MyStoredProcedure( this.jdbcTemplate );
Map<String, Object> result = new HashMap<String, Object>();
try
{
result = sp.execute();
}
catch( DataAccessException dae)
{
}
System.out.println(result.size());
return null;
}
Однако размер карты всегда равен 0, поэтому ничего не возвращается. Я знаю, что в базе данных есть строки, соответствующие моим входным критериям. Кроме того, у меня была работа с кодом, которая использовала java.sql.CallableStatement
для взаимодействия с хранимой процедурой оракула - так что процесс хорош. Неправильно ли смешивать OraceleTypes.CURSOR
с Spring хранимой процедурой? Что еще я могу использовать? Я также пробовал SqlReturnResultSet
, и это тоже не сработало.
Ответы
Ответ 1
Проблема здесь в том, что Oracle способ выполнения хранимых процедур не соответствует JDBC. Oracle SPs возвращают данные результатов через параметры OUT или возвращают значения, которые являются курсорами, и их нужно обрабатывать специально. Это означает, что вы не можете использовать какой-либо материал Spring JDBC, который предполагает соответствие JDBC, вы должны сделать это самостоятельно.
На практике это означает, что вы должны использовать JdbcTemplate
и CallableStatementCallback
, что означает гораздо более ручную кодировку JDBC, чем вам хотелось бы, но мне еще предстоит найти способ избежать этого.
В небольшом аспекте я скорее подозреваю, что спецификация JDBC была написана так, чтобы она соответствовала способу выполнения Sybase (и, благодаря ассоциации, SQL Server), потому что способ хранения хранимых процедур в JDBC - замечательно хороший подходит для этих систем (и плохо подходит для Oracle).
Ответ 2
Проблема проста, если вы не передаете RowMapper при объявлении outparam, который является CURSOR. Spring будет возвращать {}
I. пустой символ.
declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR)); - returns empty {}
declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR, new ApplicationMapper()); - returns result
Где ApplicationMapper - это мой настраиваемый mapper, который реализует RowMapper.