Как использовать параметр IN OUT в хранимой процедуре Oracle с Spring-jdbc?

В моей хранимой процедуре у меня четыре параметра. Один из параметров имеет как IN, так и OUT. Я столкнулся с проблемами при доступе к параметру с помощью IN и Out.

При обычном подходе (с использованием CallableStatement) я могу получить результаты. Я столкнулся с этой проблемой при использовании CallableStatementCreatorFactory (используя это, чтобы избежать проблемы с Sonarqube). Я ищу решение с помощью CallableStatementCreatorFactory. Я не могу внести никаких изменений в хранимую процедуру.

Процедура

PROCEDURE SOMENAME (
applicationname           IN     VARCHAR2,
username                  IN OUT VARCHAR2,
sessionid                 IN     VARCHAR2 DEFAULT NULL,
usertype                  OUT    VARCHAR2,

Весенний загрузочный код

public static final String STORED_PROCEDURE_SOME_NAME = "{call TEST.PKG.SOMENAME(?,?,?,?)}";

CallableStatementCreatorFactory callableStatementCreatorFactory = new CallableStatementCreatorFactory(STORED_PROCEDURE_SOME_NAME);
callableStatementCreatorFactory.addParameter(new SqlParameter("APPLICATIONNAME", OracleTypes.VARCHAR));
callableStatementCreatorFactory.addParameter(new SqlParameter("USERNAME", OracleTypes.VARCHAR));
callableStatementCreatorFactory.addParameter(new SqlParameter("sessionid", OracleTypes.VARCHAR));
//callableStatementCreatorFactory.addParameter(new SqlOutParameter("USERNAME", OracleTypes.VARCHAR));  - throwing issue
callableStatementCreatorFactory.addParameter(new SqlOutParameter("usertype", OracleTypes.VARCHAR));

final Map<String, Object> param = new HashMap<>();
param.put("APPLICATIONNAME", applicationName);
param.put("USERNAME", userName);
param.put("sessionid", sessionGuid);


CallableStatementCallback<User> callableStatementCallback = new CallableStatementCallback<User>()
{
@Override
public User doInCallableStatement(CallableStatement callableStatement) throws SQLException
{
  try
  {
    callableStatement.execute();
    User userModel = new User();
    //userModel.setUserName(callableStatement.getString(2));  - throwing issue
    userModel.setUserType(callableStatement.getString(4));
    return populateUser(callableStatement);
  }
  finally
  {
    try
    {
      callableStatement.close();
    }
    catch (SQLException e)
    {
      LOGGER.error(MESSAGE_ERROR_CALLABLESTATEMENT_CLOSE, e);
    }
  }
}
};

CallableStatementCreator callableStatementCreator = callableStatementCreatorFactory.newCallableStatementCreator(param);
userModel = jdbcTemplate.execute(callableStatementCreator, callableStatementCallback);

Когда я добавляю дополнительную букву? 'в запросе я получаю следующее исключение:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call TEST.PKG.SOMENAME(?,?,?,?,?)}]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'SOMENAME'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Когда я раскомментирую следующую строку, у меня возникает следующая проблема (удален дополнительный вопросительный знак):

callableStatementCreatorFactory.addParameter(new SqlOutParameter("USERNAME", OracleTypes.VARCHAR)); 

Исключение

org.springframework.jdbc.InvalidResultSetAccessException: CallableStatementCallback; invalid ResultSet access for SQL [{call TEST.PKG.SOMENAME(?,?,?,?)}]; nested exception is java.sql.SQLException: Invalid column index

Когда я раскомментирую следующую строку, я получаю следующую ошибку:

userModel.setUserName(callableStatement.getString(TWO));  (after commenting previous line and removing one addtional ?)

Исключение

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call TEST.PKG.SOMENAME(?,?,?,?)}]; SQL state [99999]; error code [17021]; Missing defines; nested exception is java.sql.SQLException: Missing defines
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
3 094
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш параметр - это параметр IN OUT, поэтому вы должны использовать для него SqlInOutParameter.

Заменить строку

    callableStatementCreatorFactory.addParameter(new SqlParameter("USERNAME", OracleTypes.VARCHAR));

с участием

    callableStatementCreatorFactory.addParameter(new SqlInOutParameter("USERNAME", OracleTypes.VARCHAR));

Не добавляйте дополнительный ?, у хранимой процедуры четыре параметра.

Удалите закомментированную строку, которая пытается создать SqlOutParameter для USERNAME. Однако вы можете раскомментировать строку

    //userModel.setUserName(callableStatement.getString(2));  - throwing issue

и используйте эту строку, чтобы прочитать имя пользователя, полученное вами из базы данных.

Я внес эти изменения в ваш код и смог использовать его для вызова процедуры с той же подписью, что и ваша, и считывания данных из процедуры.

Между прочим, не закрывайте оператор в CallableStatementCallback: я обнаружил, что это вызывает исключение, потому что Spring будет делать другие вещи с оператором после того, как вы закончите с ним, но он не может этого сделать, если вы закрыли оператор. . Spring закроет оператор, когда закончит с ним. Одним из преимуществ использования Spring для создания JDBC является то, что он обрабатывает множество утомительных шаблонных вещей, подобных этому.

Спасибо, @ Люк Вудворд. Предоставленное вами решение сработало отлично. Ты спас мне день. Еще раз спасибо.

Thiagarajan Ramanathan 23.11.2018 22:57

Другие вопросы по теме