1

考虑以下 DDL,我在其中一个 JUnit 测试用例中使用它来创建 H2 数据库表:

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 代码正在传递“20 年 1 月 31 日”,没有时间戳组件,这也可以从上面的错误消息中看出。

如何解决此错误?

4

2 回答 2

2

java.time

最好的解决方案是使用智能对象而不是哑字符串与数据库交换值。具体来说,使用现代java.time类。

您的输入使用全大写的月份名称。这不符合英语的本地化,至少不符合美国或英国英语。所以我们必须使用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以防输入错误。

使用与 JDBC 4.2 或更高版本兼容的 JDBC 驱动程序传递到数据库。

myPreparedStatement.setObject( … , LocalDate ) ;

取回。

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

提示:向您的数据发布者介绍ISO 8601标准格式,以便将日期时间值交换为文本。

于 2020-04-13T15:36:44.023 回答
1

您需要使用 H2 函数PARSEDATETIME()将日期格式化为数据库期望的格式。

在这里的第二个答案中,您将看到一个几乎使用您的确切格式的示例。

在H2中将特殊字符串转换为日期

或者将您的数据重新格式化为 ISO 标准,在您的情况下应该是yyyy-MM-dd

于 2020-04-13T08:02:07.400 回答