База данных H2: Невозможно проанализировать константу «DATE» «31-JAN-20» при вставке новой записи. - PullRequest
1 голос
/ 13 апреля 2020

Рассмотрим следующий DDL, который я использую для создания таблицы базы данных H2 в одном из моих тестовых примеров JUnit:

CREATE TABLE "CONFIG_INFO" 
   (    "ID" VARCHAR2(12 BYTE), 
        "RUN_DATE" DATE, 
   );

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

insert into CONFIG_INFO(ID,RUN_DATE) values (?,?) 

Однако вставка завершается неудачно со следующим исключением:

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [insert into CONFIG_INFO(ID,RUN_DATE) values (?,?)]; Cannot parse "DATE" constant "31-Jan-20"; 

Я посмотрел вокруг и обнаружил, что эта проблема обычно происходит, когда у вас есть компонент времени как часть даты; однако отладил код, и я вижу, что код Java проходит «31-Jan-20» без компонента отметки времени, что также видно из сообщения об ошибке выше.

Как я могу решить эту ошибку?

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

java .time

Лучшее решение - использовать умные объекты, а не тупые строки для обмена значениями с вашей базой данных. В частности, используйте современные java .time классы.

В качестве вводимых данных используется название месяца в верхнем регистре. Это не соответствует локализации для Engli sh, по крайней мере, в США или Великобритании Engli sh. Поэтому мы должны использовать DateTimeFormatterBuilder, чтобы получить DateTimeFormatter, который допускает все заглавные буквы.

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern( "dd-MMM-uu" ) ;
DateTimeFormatter formatter = builder.toFormatter() ;

Разобрать вашу входную строку.

String input = "31-JAN-20" ;
LocalDate localDate = LocalDate.parse( input , formatter ) ;

Ловушка для DateTimeParseException в случае неисправности входы.

Передача в базу данных с использованием драйвера JDB C, совместимого с JDB C 4.2 или более поздней.

myPreparedStatement.setObject( … , LocalDate ) ;

Извлечение.

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

Совет : Сообщите издателю ваших данных о стандартных форматах ISO 8601 для обмена значениями даты и времени в виде текста.

1 голос
/ 13 апреля 2020

Вам потребуется использовать функцию H2 PARSEDATETIME(), чтобы отформатировать дату в формате, ожидаемом базой данных.

Во втором ответе здесь вы увидите пример, который использует почти ваш точный формат.

Преобразование специальной строки в дату в H2

Или переформатировать ваши данные в стандарт ISO, который в вашем случае должен быть yyyy-MM-dd

...