在内存 DB 中的 H2 中插入日期时 DateTimeFormat 无效

Invalid DateTimeFormat when inserting date in H2 in memory DB

我在尝试将值插入内存中的 H2 数据库时遇到问题。

我有这个实体:

@Entity
@Table(name="myTable")
public class MyEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    @Column(name = "startDate")
    @DateTimeFormat(pattern="yyy-MM-dd-HH.mm.ss")
    private Date startDate;
    
    @Column(name = "endDate")
    @DateTimeFormat(pattern="yyy-MM-dd-HH.mm.ss")
    private Date endDate;
}

我使用了 yyy-MM-dd-HH.mm.ss 模式,因为日期的格式类似于 2021-06-14-00.00.002021-12-31-23.59.59.

导入的@DateTimeFormatorg.springframework.format.annotation.DateTimeFormat;Datejava.util.Date

要在数据库中插入值,我有这个脚本:

INSERT INTO myTable (ID, START_DATE, END_DATE) VALUES
(1, '2020-08-07-00.00.00', '2021-12-31-23.59.59'),
(2, '2020-04-03-14.00.00', '2021-01-14-18.30.00'),
(3, '2020-09-15-00.00.00', '2021-06-15-11.00.00'),
(4, '2020-01-18-16.00.00', '2021-12-31-23.59.59');

但它抛出一个错误:

Caused by: org.h2.jdbc.JdbcSQLDataException: Imposible interpretar la constante "TIMESTAMP" "2021-12-31-23.59.59"
Cannot parse "TIMESTAMP" constant "2021-12-31-23.59.59"; SQL statement:
INSERT INTO myTable (ID, ...

...

Caused by: java.lang.NumberFormatException: 31-23.59.59

错误中的非英文文本类似于“无法解释常量“TIMESTAMP””。

我还测试了一些东西,(这很重要!)删除小时、分钟和秒,程序运行正常,所以我假设模式不是正确。

此 SQL 脚本有效:

INSERT INTO myTable (ID, START_DATE, END_DATE) VALUES
(1, '2020-08-07', '2021-12-31'),
(2, '2020-04-03', '2021-01-14'),
(3, '2020-09-15', '2021-06-15'),
(4, '2020-01-18', '2021-12-31');

我已经检查了 DateTimeFormat tester online,我的模式的当前日期是 2021-12-21-17.44.32,但即使仅使用该日期创建 table 也会引发错误。

有关 table 的更多信息:
table(以及列)是使用 spring.jpa.hibernate.ddl-auto=update 创建的,因此我假设列类型为 DATE(作为实体字段)。

所以我试图在 DATE 列中插入格式为 yyy-MM-dd-HH.mm.ss 的字符串(如果我没记错的话)。

所以,问题是什么?无法将此模式作为日期从内存数据库中的 H2 中的字符串插入?

提前致谢。

如果您只是想将 java.util.Date 插入 TIMESTAMP 列,则不需要 @DateTimeFormat。你没有解析任何东西,你从 Date 对象中分离出来,JPA 将它转换成正确的 SQL 数据类型。

这样定义列:

    @Column(name = "startDate")
    @Temporal(value=TemporalType.DATE)
    private Date startDate;
    

你应该可以开始了。

更新

如果只有 DATE 模式有效,而 TIMESTAMP 模式均无效,则表示该列定义了错误的数据类型。 DATE 和 TIMESTAMP 是两种不同的 H2 数据类型(在所有其他 DDBB 中,但名称可能不同)

您的问题不在于 Java 代码中定义的 JPA 层,而是您执行的脚本。

INSERT INTO myTable (ID, START_DATE, END_DATE) VALUES
(1, '2020-08-07-00.00.00', '2021-12-31-23.59.59'),
(2, '2020-04-03-14.00.00', '2021-01-14-18.30.00'),
(3, '2020-09-15-00.00.00', '2021-06-15-11.00.00'),
(4, '2020-01-18-16.00.00', '2021-12-31-23.59.59');

这与您定义 JPA 层的方式无关。对于该脚本,执行时 @DateTimeFormat(pattern="yyy-MM-dd-HH.mm.ss") 完全不知道您在代码中定义了它。

这只是在数据库中执行的脚本。数据库如何知道如何将此字符串转换为有效的日期对象?您必须在脚本中告知必须如何从字符串转换为日期。

以下内容应该有效,因为 PARSEDATETIME 是 H2 的函数。

INSERT INTO myTable (ID, START_DATE, END_DATE) VALUES (1, PARSEDATETIME('2020-08-07-00.00.00','yyyy-MM-dd-HH.mm.ss'), PARSEDATETIME('2021-12-31-23.59.59','yyyy-MM-dd-HH.mm.ss') 

还请仔细检查您执行的内容 yyy-MM-dd-HH.mm.ssyyy 不符合您在 ex 2020 脚本中设置的年龄。这是 yyyy

有点晚了,但还是:)

假设 (h2, in-mem):

CREATE TABLE myTable(Id NUMBER primary key,START_DATE TIMESTAMP,END_DATE 
TIMESTAMP);

然后:

INSERT INTO myTable (ID, START_DATE, END_DATE) VALUES

喜欢:

(1, {ts '2020-08-07 00:00:00'}, {ts '2021-12-31 23:59:59'}),

(标准时间格式)

或:

(2, parsedatetime('2020-04-03-14.00.00', 'yyyy-MM-dd-HH.mm.ss'), 
    parsedatetime('2021-01-14-18.30.00', 'yyyy-MM-dd-HH.mm.ss'));

(定制的)

参考文献: