Reputation: 21081
I'm using Java 8 for my new project.
I'm trying to use new date and time api in java 8 however I don't know if JPA 2.1
fully supports this new Date and Time API or not.
Please share your experience/opinion in JPA`s supports for new date and time API in Java 8.
Can I use new date and time api in Java 8 safely with JPA 2.1?
UPDATE:
I'm using Hibernate (4.3.5.Final) as JPA implementation.
Upvotes: 58
Views: 52025
Reputation: 191
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 error, but the data type of the column will be bytea in the database. You can only read it from a Java application as far i know.
However, you can use AttributeConverter
to convert these classes to java.sql.Date
. I found this code from 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();
}
Upvotes: 9
Reputation: 21081
JPA 2.2 now supports LocalDate
, LocalTime
, LocalDateTime
, OffsetTime
and OffsetDateTime
.
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
For JPA 2.2 implementation, Hibernate 5.2 or EclipseLink 2.7 can be used.
Hibernate 5 supports more java types than JPA 2.2 like Duration
, Instant
and ZonedDateTime
.
More Info:
Upvotes: 13
Reputation: 53
For type TIMESTAMP you can use this converter:
@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 DATE you can use this converter:
@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 TIME you can use this converter:
@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();
}
}
Upvotes: 1
Reputation: 2587
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-
@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
2- The other ways is to use jpa @PostLoad @PreUpdate @PrePersist
@PostLoad
public void convert() {
this.jva8Date= LocalDate.now().plusDays(1);
}
or use temp one such
@Transient
public LocalDateTime getCreatedDateTime() {
return createdTime.getLocalDateTime();
}
Upvotes: 0
Reputation: 17980
For Hibernate 5.X just add
<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
UPDATE:
Please have a look at Jeff Morin comment: since Hibernate 5.2.x it is enough
<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.2 and Integrate Hibernate 5.2 with Spring framework 4.x
Upvotes: 73
Reputation: 11531
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.
It has been requested that JPA 2.2 support the java.time types, see this issue https://java.net/jira/browse/JPA_SPEC-63
Upvotes: 21
Reputation: 17722
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:
@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.
Upvotes: 3
Reputation: 21081
org.jadira.usertype can be used to persist JSR 310 Date and Time 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;
}
Upvotes: 9