我正在使用Java 8开发我的新项目。
我试图在Java 8中使用新的日期和时间API,但是我不知道JPA 2.1是否完全支持这个新的日期和时间API。
请分享您在JPA对Java 8新日期和时间API支持方面的经验/观点。
我能否安全地在Java 8中使用新的日期和时间API与JPA 2.1一起工作?
更新:
我正在使用Hibernate(4.3.5.Final)作为JPA实现。
我正在使用Java 8开发我的新项目。
我试图在Java 8中使用新的日期和时间API,但是我不知道JPA 2.1是否完全支持这个新的日期和时间API。
请分享您在JPA对Java 8新日期和时间API支持方面的经验/观点。
我能否安全地在Java 8中使用新的日期和时间API与JPA 2.1一起工作?
更新:
我正在使用Hibernate(4.3.5.Final)作为JPA实现。
对于 Hibernate 5.X,只需添加:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>${hibernate.version}</version>
</dependency>
和
@NotNull
@Column(name = "date_time", nullable = false)
protected LocalDateTime dateTime;
将不需要任何额外的努力即可工作。 请参见https://hibernate.atlassian.net/browse/HHH-8844
更新:
请查看Jeff Morin的评论:自Hibernate 5.2.x起,这已经足够了。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.1.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-...</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
请查看https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2和Integrate Hibernate 5.2 with Spring framework 4.x
JPA 2.1是在Java 1.8之前发布的规范,因此不强制要求支持它。显然,一些实现可能会支持一些Java 1.8功能。有些实现可能存在Java 1.8字节码问题(例如EclipseLink)。我知道DataNucleus支持java.time和Java 1.8,因为那是我使用的。您需要检查您的实现以确定其支持级别。
已经要求JPA 2.2支持java.time类型,请参见此问题 https://java.net/jira/browse/JPA_SPEC-63
JPA 2.2现在支持LocalDate
、LocalTime
、LocalDateTime
、OffsetTime
和OffsetDateTime
。
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
对于JPA 2.2实现,可以使用Hibernate 5.2或EclipseLink 2.7。
Hibernate 5支持比JPA 2.2更多的Java类型,如Duration
,Instant
和ZonedDateTime
。
更多信息:
org.jadira.usertype可以用于持久化JSR 310日期和时间API。
查看此示例项目。
来自示例项目,
@MappedSuperclass
public class AbstractEntity {
@Id @GeneratedValue Long id;
@CreatedDate//
@Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
ZonedDateTime createdDate;
@LastModifiedDate//
@Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime")//
ZonedDateTime modifiedDate;
}
LocalDateTime
变量而不出现错误,但数据库中列的数据类型将为bytea。据我所知,你只能从Java应用程序中读取它。AttributeConverter
将这些类转换为java.sql.Date
。我从Java.net中找到了这个代码。@Converter(autoApply = true)
public class LocalDatePersistenceConverter implements
AttributeConverter {
@Override
public java.sql.Date convertToDatabaseColumn(LocalDate entityValue) {
return java.sql.Date.valueOf(entityValue);
}
@Override
public LocalDate convertToEntityAttribute(java.sql.Date databaseValue) {
return databaseValue.toLocalDate();
}
@Entity
public class Person {
private Long id;
private Timestamp createdTimestamp;
@Id
@GeneratedValue
public Long getId() { return id; }
private Timestamp getCreatedTimestamp() {
return createdTime;
}
private void setCreatedTimestamp(final Timestamp ts) {
this.createdTimestamp = ts;
}
@Transient
public LocalDateTime getCreatedDateTime() {
return createdTime.getLocalDateTime();
}
public void setCreatedDateTime(final LocalDateTime dt) {
this.createdTime = Timestamp.valueOf(dt);
}
}
您使用公共的getter/setter方法来操作新的Java 8日期/时间类,但在幕后,getter/setter方法使用旧的日期/时间类。当您持久化实体时,旧的日期/时间属性将被持久化,但由于新的Java 8属性带有@Transient注释,因此不会持久化新的Java 8属性。
@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime datetime) {
return datetime == null ? null : Timestamp.valueOf(datetime);
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp timestamp) {
return timestamp == null ? null : timestamp.toLocalDateTime();
}
}
对于类型日期,您可以使用此转换器:
@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate date) {
return date == null ? null : Date.valueOf(date);
}
@Override
public LocalDate convertToEntityAttribute(Date date) {
return date == null ? null : date.toLocalDate();
}
}
对于类型 TIME ,您可以使用此转换器:
@Converter(autoApply = true)
public class LocalTimeAttributeConverter implements AttributeConverter<LocalTime, Time> {
@Override
public Time convertToDatabaseColumn(LocalTime time) {
return time == null ? null : Time.valueOf(time);
}
@Override
public LocalTime convertToEntityAttribute(Time time) {
return time == null ? null : time.toLocalTime();
}
}
有许多方法可以做到这一点,也取决于您的框架: 如果您的框架具有现场转换器,例如Spring,请执行以下操作: 1-
@DateTimeFormat(pattern = "dd.MM.yyyy - HH:mm")
private Long createdDate;
这里我正在使用传统的纪元格式https://www.epochconverter.com/ 纪元是非常灵活和被接受的格式
2- 另一种方法是使用jpa @PostLoad @PreUpdate @PrePersist
@PostLoad
public void convert() {
this.jva8Date= LocalDate.now().plusDays(1);
}
或者使用临时变量
@Transient
public LocalDateTime getCreatedDateTime() {
return createdTime.getLocalDateTime();
}