Как использовать параметр IN OUT в хранимой процедуре Oracle с spring-jdbc? - PullRequest
0 голосов
/ 23 ноября 2018

В моей хранимой процедуре у меня есть четыре параметра.Один из параметров имеет как 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

1 Ответ

0 голосов
/ 23 ноября 2018

Ваш параметр является параметром 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 является то, что он обрабатывает множество таких утомительных шаблонов, как этот.

...