У меня есть код:
@PersistenceContext
private EntityManager em;
public void call() {
String input = "<ROOT>" +
"<START_DATE>20240824</START_DATE>" +
"</ROOT>";
StoredProcedureQuery proc = em.createStoredProcedureQuery("procedureName");
proc.registerStoredProcedureParameter("inXml", String.class, ParameterMode.IN);
proc.registerStoredProcedureParameter("outXml", String.class, ParameterMode.OUT);
proc.registerStoredProcedureParameter("error", String.class, ParameterMode.OUT);
proc.setParameter("inXml", input);
proc.execute();
var outXml = (String) proc.getOutputParameterValue("outXml");
var error = (String) proc.getOutputParameterValue("error");
log.info(outXml);
log.info(error);
}
Это приложение Spring Boot (версия 3.0.7). Я вызываю хранимую процедуру в базе данных Oracle с датой в качестве параметра. Я запускаю код на двух компьютерах:
1. Java установлена = openjdk version "17.0.9" 2023-10-17 OpenJDK Runtime Environment Temurin-17.0.9+9 (build 17.0.9+9) OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode, sharing)
2. Java установлена = openjdk version "17.0.2" 2022-01-18 OpenJDK Runtime Environment (build 17.0.2+8-86) OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)
Номер 1 работает нормально, но номер 2 выдает ошибку = ORA-01861: literal does not match format string
Не могли бы вы сказать мне, почему тот же код не работает на сервере номер 2?
Вы пробовали свой код в SQL-клиенте?
Да, код в Oracle SQL Developer работает нормально
ошибка связана с процедурой, что формат даты неверен, но это одна и та же строка в обоих приложениях
Затем вы должны опубликовать код процедуры со строкой ошибки.
Пожалуйста, предоставьте реальный код, который дает сбой, а не только тот, который его вызывает.
У меня нет исходного кода хранимой процедуры, которую я вызываю, поскольку она принадлежит сторонней компании.
Программы подключаются к одному и тому же серверу, но каждое из двух подключений запускает разные сеансы, и эти сеансы (по какой-то причине) имеют разные параметры сеанса NLS.
Где-то в вашей процедуре вы выполняете неявное преобразование строки в DATE
:
NLS_DATE_FORMAT
соответствует YYYYMMDD
, и неявное преобразование завершается успешно.NLS_DATE_FORMAT
не соответствует YYYYMMDD
, и неявное преобразование завершается с ошибкой ORA-01861: literal does not match format string
.Решение состоит в том, чтобы НИКОГДА не полагаться на неявные преобразования.
Вы не предоставляете исходный код своей процедуры, но если вы используете TO_DATE(value)
, измените его, чтобы использовать модель явного формата TO_DATE(value, 'YYYYMMDD')
. Аналогично, если вы полагаетесь на неявные преобразования в функциях XML, не полагайтесь на неявное преобразование; сделайте это явным.
Альтернативное решение — создать триггер входа в систему, чтобы в начале каждого запускаемого вами сеанса:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMMDD';
Чтобы установить модель формата, которую Oracle использует для неявных преобразований строк в дату (и наоборот). Однако это не лучшая практика, и вам следует исправить свой код, чтобы он не полагался на неявные преобразования.
У меня нет исходного кода хранимой процедуры, которую я вызываю, поскольку она принадлежит сторонней компании, поэтому можно решить проблему, учитывая, что я не могу изменить хранимую процедуру в Oracle?
Сервер номер 2 расположен в другой стране, чем страна, в которой выполняется процедура оракула. Может ли это быть причиной несоответствия параметров сеанса NLS?
@ newuser123123 Вы можете посмотреть stackoverflow.com/q/1079985/1509264 потому что драйвер Oracle JDBC, вероятно, извлекает настройки NLS из локали (что означает, что вы получите разные настройки NLS на разных территориях мира). В качестве альтернативы, как упоминалось в ответе, посмотрите на запуск ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMMDD'
один раз после создания соединения с сервером (вы можете сделать это как триггер входа в систему, но если у вас нет контроля над сервером, вы можете запустить его вручную).
MT0, спасибо за помощь, вы прекрасно поняли мою проблему. Проблема решена сейчас.
Может быть, вы могли бы поделиться трассировкой стека исключения?