JPA 支持 Java 8 新日期和时间 API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23718383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:51:15  来源:igfitidea点击:

JPA support for Java 8 new date and time API

javajpajava-8jpa-2.1java-time

提问by TheKojuEffect

I'm using Java 8 for my new project.

我在我的新项目中使用 Java 8。

I'm trying to use new date and time api in java 8 however I don't know if JPA 2.1fully supports this new Date and Time API or not.

我正在尝试在 java 8 中使用新的日期和时间 API,但是我不知道是否JPA 2.1完全支持这个新的日期和时间 API。

Please share your experience/opinion in JPA`s supports for new date and time API in Java 8.

请分享您在 JPA 对 Java 8 中新日期和时间 API 的支持方面的经验/意见。

Can I use new date and time api in Java 8 safely with JPA 2.1?

我可以在 JPA 2.1 中安全地使用 Java 8 中的新日期和时间 api 吗?

UPDATE:

更新:

I'm using Hibernate (4.3.5.Final) as JPA implementation.

我使用 Hibernate (4.3.5.Final) 作为 JPA 实现。

采纳答案by Neil Stockton

JPA 2.1 is a spec that came out before Java 1.8, so doesn't mandate any support for it. Obviously some implementations may support some Java 1.8 features. Some have problems with Java 1.8 bytecode (e.g EclipseLink). I know DataNucleus supports java.time and Java 1.8 since that's the one I use. You'd have to check your implementation for what its support level is.

JPA 2.1 是在 Java 1.8 之前出现的规范,因此不强制要求对其提供任何支持。显然,某些实现可能支持某些 Java 1.8 特性。有些人在 Java 1.8 字节码(例如 EclipseLink)方面存在问题。我知道 DataNucleus 支持 java.time 和 Java 1.8,因为这是我使用的那个。您必须检查您的实现以了解其支持级别。

It has been requested that JPA 2.2 support the java.time types, see this issue https://java.net/jira/browse/JPA_SPEC-63

已请求 JPA 2.2 支持 java.time 类型,请参阅此问题https://java.net/jira/browse/JPA_SPEC-63

回答by Ismael_Diaz

I am using Java 8, EclipseLink(JPA 2.1),PostgreSQL 9.3 and PostgreSQL Driver -Postgresql-9.2-1002.jdbc4.jar in my project and i can use LocalDateTime variables from the new API with no problem but the data type of the column is bytea in the database, so you only can read it from a Java aplication as far i know. You can use AttributeConverter to convert the new classes to java.sql.Date I find this code from Java.net

我在我的项目中使用 Java 8、EclipseLink(JPA 2.1)、PostgreSQL 9.3 和 PostgreSQL 驱动程序 -Postgresql-9.2-1002.jdbc4.jar,我可以使用来自新 API 的 LocalDateTime 变量没有问题,但列的数据类型是数据库中的字节,因此据我所知,您只能从 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();
}

回答by TheKojuEffect

org.jadira.usertypecan be used to persist JSR 310 Date and Time API.

org.jadira.usertype可用于持久化 JSR 310 日期和时间 API。

Check out this example project.

查看此示例项目

From Example Project,

从示例项目,

@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;
}

回答by Jin Kim

I know that this is an old question but I thought of an alternative solution which might be helpful.

我知道这是一个老问题,但我想到了一个可能有用的替代解决方案。

Instead of trying to map the new java.time.* classes to an existing database types, you can leverage @Transient:

您可以利用@Transient,而不是尝试将新的 java.time.* 类映射到现有的数据库类型:

@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);
    }
}

You work with the public getter/setter methods that use the new Java 8 date/time classes, but behind the scenes the getter/setters work with the legacy date/time classes. When you persist the entity, the legacy date/time property will be persisted but not the new Java 8 property since it's annotated with @Transient.

您使用使用新 Java 8 日期/时间类的公共 getter/setter 方法,但在幕后,getter/setter 使用旧的日期/时间类。当您保留实体时,将保留旧的日期/时间属性,但不会保留新的 Java 8 属性,因为它使用 @Transient 进行了注释。

回答by Grigory Kislin

For Hibernate 5.X just add

对于 Hibernate 5.X 只需添加

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-java8</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

and

@NotNull
@Column(name = "date_time", nullable = false)
protected LocalDateTime dateTime;

will work without any additional effort. See https://hibernate.atlassian.net/browse/HHH-8844

无需任何额外努力即可工作。见https://hibernate.atlassian.net/browse/HHH-8844

UPDATE:

更新:

Please have a look at Jeff Morin comment: since Hibernate 5.2.x it is enough

请看一下 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>

See https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2and Integrate Hibernate 5.2 with Spring framework 4.x

请参阅https://github.com/hibernate/hibernate-orm/wiki/Migration-Guide---5.2并将 Hibernate 5.2 与 Spring 框架 4.x 集成

回答by Ali.Mojtehedy

There are Many approach to do , Also It depends to your frame work : If your frame work has on field Converter such spring do such: 1-

有很多方法可以做,这也取决于您的框架:如果您的框架在现场转换器上有这样的弹簧,请执行以下操作:1-

@DateTimeFormat(pattern = "dd.MM.yyyy - HH:mm")
private Long createdDate;

here I am using legacy epoch format https://www.epochconverter.com/epoch is very flexible and accepted format

在这里,我使用旧时代格式https://www.epochconverter.com/时代是非常灵活和可接受的格式

2- The other ways is to use jpa @PostLoad @PreUpdate @PrePersist

2-其他方法是使用 jpa @PostLoad @PreUpdate @PrePersist

@PostLoad
      public void convert() {
        this.jva8Date= LocalDate.now().plusDays(1);
      }

or use temp one such

或使用 temp 之一

@Transient
public LocalDateTime getCreatedDateTime() {
    return createdTime.getLocalDateTime();
}

回答by TheKojuEffect

JPA 2.2 supports java.time

JPA 2.2 支持 java.time

JPA 2.2now supports LocalDate, LocalTime, LocalDateTime, OffsetTimeand OffsetDateTime.

JPA 2.2现在支持LocalDateLocalTimeLocalDateTimeOffsetTimeOffsetDateTime

<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>javax.persistence-api</artifactId>
  <version>2.2</version>
</dependency>

For JPA 2.2 implementation, Hibernate 5.2or EclipseLink 2.7can be used.

对于 JPA 2.2 实现,可以使用Hibernate 5.2EclipseLink 2.7

Hibernate 5 supports more java types than JPA 2.2 like Duration, Instantand ZonedDateTime.

与 JPA 2.2 相比,Hibernate 5 支持更多的 java 类型,例如Duration,InstantZonedDateTime.

More Info:

更多信息:

回答by Paco

For type TIMESTAMPyou can use this converter:

对于TIMESTAMP类型,您可以使用此转换器:

@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();
    }

}

For type DATEyou can use this converter:

对于DATE类型,您可以使用此转换器:

@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();
    }

}

For type TIMEyou can use this converter:

对于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();
    }

}