如何将时间戳列映射到分区日期时间 JPA 实体属性?



我正在使用Spring 数据 jpamariadb最新版本,以及MariaDB 10.3.16

+--- org.springframework.boot:spring-boot-starter-data-jpa -> 2.1.5.RELEASE
...
|    +--- org.springframework.boot:spring-boot-starter-jdbc:2.1.5.RELEASE
...
|    +--- org.hibernate:hibernate-core:5.3.10.Final

这是我的实体:

@Entity
@Data
@Table
@NoArgsConstructor
@AllArgsConstructor
public class Note {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Column
private String gsn;
@Column
@Enumerated(EnumType.STRING)
private NoteType type;
@Column
private String text;
@Column
private ZonedDateTime scheduleDt;
@Column
@CreationTimestamp
private Instant createDt;
@Column
@UpdateTimestamp
private ZonedDateTime updateDt;
}

当我保留我的实体时,Hibernate尝试ZonedDateTime成员另存为DATETIME列。但是我想使用时间戳列而不是日期时间列。

这是创建DDL,我从日志中看到的。

create table `note` (`id` integer not null, `create_dt` datetime,
`gsn` varchar(255), `schedule_dt` datetime, `text` varchar(255),
`type` varchar(255), `update_dt` datetime, primary key (`id`)) 
engine=MyISAM

这里create_dtschedule_dtupdate_dt被创建为datetime列类型,这不是我想要的。(我也不喜欢MyISAM)。

我该如何解决它?


添加是因为注释无法表达 ddl。

当我使用列定义属性时,生成的 ddl 是...

create table `note` (`id` integer not null, `create_dt` datetime,
`gsn` varchar(255), `schedule_dt` datetime, `text` varchar(255),
`type` varchar(255), `update_dt` `TIMESTAMP`, primary key (`id`)) 

引擎=我的ISAM

时间戳周围有不需要的"。

JPA 2.2 支持映射 Java 8 日期/时间 API,但仅适用于以下类型:

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.OffsetTime
  • java.time.OffsetDateTime

但是,Hibernate也支持ZonedDateTime,就像这样。

保存ZonedDateTime时,以下Timestamp将被发送到PreparedStatement

Timestamp.from( zonedDateTime.toInstant() )

并且,从数据库中读取它时,ResultSet将包含一个将转换为ZonedDateTimeTimestamp,如下所示:

ts.toInstant().atZone( ZoneId.systemDefault() )

请注意,ZoneId不存储在数据库中,因此基本上,如果此Timestamp转换不适合您,则最好使用LocalDateTime

因此,让我们假设我们有以下实体:

@Entity(name = "UserAccount")
@Table(name = "user_account")
public class UserAccount {
@Id
private Long id;
@Column(name = "first_name", length = 50)
private String firstName;
@Column(name = "last_name", length = 50)
private String lastName;
@Column(name = "subscribed_on")
private ZonedDateTime subscribedOn;
//Getters and setters omitted for brevity
}

请注意,subscribedOn属性是一个ZonedDateTimeJava 对象。

持久保存UserAccount时:

UserAccount user = new UserAccount()
.setId(1L)
.setFirstName("Vlad")
.setLastName("Mihalcea")
.setSubscribedOn(
LocalDateTime.of(
2020, 5, 1,
12, 30, 0
).atZone(ZoneId.systemDefault())
);
entityManager.persist(user);

Hibernate生成正确的SQL INSERT语句:

INSERT INTO user_account (
first_name, 
last_name, 
subscribed_on, 
id
) 
VALUES (
'Vlad', 
'Mihalcea', 
'2020-05-01 12:30:00.0', 
1
)

在获取UserAccount实体时,我们可以看到ZonedDateTime是从数据库中正确获取的:

UserAccount userAccount = entityManager.find(
UserAccount.class, 1L
);
assertEquals(
LocalDateTime.of(
2020, 5, 1,
12, 30, 0
).atZone(ZoneId.systemDefault()),
userAccount.getSubscribedOn()
);

您可以使用@Column注释定义列类型:

@Column(columnDefinition="TIMESTAMP")  
@UpdateTimestamp
private ZonedDateTime updateDt;

最新更新