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




Ваш параметр - это параметр 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 является то, что он обрабатывает множество утомительных шаблонных вещей, подобных этому.
Спасибо, @ Люк Вудворд. Предоставленное вами решение сработало отлично. Ты спас мне день. Еще раз спасибо.