JPA support for Java 8 new date and time API
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
JPA and java 8 date API - choosing correct implementation (Instant, LocalDateTime, ZonedDateTime)
Instant
is by by definition UTC, so if you are always dealing with UTC, it is sufficient if it has all of the operations you need. LocalDateTime
is a timestamp without a specific time zone or zone offset, but if you know you are only dealing with UTC, it can be useful for the operations it provides that Instant
does not.
The most exact type that can carry a definite zone offset, allowing you to preserve the moment of time while converting back and forth between UTC and other time zones is OffsetDateTime
. There is a convenient ZoneOffset.UTC
constant that you can use to fix the offset at +0 hours for UTC. ZonedDateTime
adds the concept of a TimeZone
which adds support for things like daylight savings time, a concept which you generally don't need when dealing with UTC unless you want to display the local time in a specific locale.
Java 8 date/time type `java.time.Instant` not supported by default Issue :
Do you have the following artifact into your project ?
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
According to the spring source code, if the class com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
is present in your classpath, the JavaTimeModule
should be registered
How to use the Java 8 LocalDateTime with JPA and Hibernate
Since Hibernate 4 doesn't support it you need to implement a user type as shown in this example.
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.usertype.EnhancedUserType;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
public class LocalDateTimeUserType implements EnhancedUserType, Serializable {
private static final int[] SQL_TYPES = new int[]{Types.TIMESTAMP};
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@Override
public Class returnedClass() {
return LocalDateTime.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true;
}
if (x == null || y == null) {
return false;
}
LocalDateTime dtx = (LocalDateTime) x;
LocalDateTime dty = (LocalDateTime) y;
return dtx.equals(dty);
}
@Override
public int hashCode(Object object) throws HibernateException {
return object.hashCode();
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Object timestamp = StandardBasicTypes.TIMESTAMP.nullSafeGet(resultSet, names, session, owner);
if (timestamp == null) {
return null;
}
Date ts = (Date) timestamp;
Instant instant = Instant.ofEpochMilli(ts.getTime());
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (value == null) {
StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, null, index, session);
} else {
LocalDateTime ldt = ((LocalDateTime) value);
Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
Date timestamp = Date.from(instant);
StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, timestamp, index, session);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object value) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public String objectToSQLString(Object object) {
throw new UnsupportedOperationException();
}
@Override
public String toXMLString(Object object) {
return object.toString();
}
@Override
public Object fromXMLString(String string) {
return LocalDateTime.parse(string);
}
}
The new usertype can then be used in the mapping with the @Type annotation. For e.g.
@Type(type="com.hibernate.samples.type.LocalDateTimeUserType")
@Column(name = "invalidate_token_date")
private LocalDateTime invalidateTokenDate;
The @Type annotation needs a full path to the class that implements the userType interface; this is the factory for producing the target type of the mapped column.
Here's how to do the same thing in JPA2.1
Related Topics
How to Detect a Click in an Ontouch Listener
Convert a String to a Byte Array and Then Back to the Original String
Xmpp with Java Asmack Library Supporting X-Facebook-Platform
Google Gson Linkedtreemap Class Cast to Myclass
"Hello World" Android App with as Few Files as Possible, No Ide, and Text Editor Only
Convert Normal Java Array or Arraylist to JSON Array in Android
How to Draw an Arrowhead (In Android)
How to Close Another App in Android
Deadobjectexception on Android App
How to Move Firebase Child from One Node to Another in Android
Tm.Getdeviceid() Is Deprecated
PDF Library to Rendering the PDF Files in Android
How to Match Nested Brackets with a Regex Without Using Recursion or Balancing Groups
How to Create My Own Appender in Log4J
How to Use an Array List in Java
How to Calculate the Pixel Width of a String in Javafx
How to Increase the Number of Displayed Lines of a Java Stack Trace Dump