У меня есть код:
@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?
🤔 А знаете ли вы, что...
Oracle Database 19c - это последняя версия базы данных Oracle на момент завершения моего обучения в сентябре 2021 года.
Программы подключаются к одному и тому же серверу, но каждое из двух подключений запускает разные сеансы, и эти сеансы (по какой-то причине) имеют разные параметры сеанса 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 использует для неявных преобразований строк в дату (и наоборот). Однако это не лучшая практика, и вам следует исправить свой код, чтобы он не полагался на неявные преобразования.