![](/img/trans.png)
[英]How to map a MySQL JSON column to a Java entity property using JPA and Hibernate
[英]How to map a TIMESTAMP column to a ZonedDateTime JPA entity property?
我正在使用 Spring 数据jpa和mariadb最新版本,以及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列。 但我想使用TIMESTAMP列而不是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_dt
、 schedule_dt
、 update_dt
被创建为datetime
列类型,这是我不想要的。 (我也不喜欢 MyISAM)。
我该如何解决?
添加是因为注释无法表达 ddl。
当我使用 columnDefinition 属性时,生成的 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`))
引擎=MyISAM
TIMESTAMP 周围有不需要的“`”。
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
将包含一个Timestamp
将被转化为一个ZonedDateTime
,就像这样:
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
属性是一个ZonedDateTime
Java 对象。
持久化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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.