Reading and Writing UTC Timestamps to DB with Hibernate
Reading and writing UTC timestamps to a database when the default timezone may change. E.g., this might happen in an application server if an application running in the same JRE changes the default timezone as follows:
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Zurich"));
The easiest solution to solve this problem I know is to create an own mapping type extending the standard Hibernate timestamp type org.hibernate.type.TimestampType
:
package ch.meteoswiss.commons.hibernate;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.SimpleTimeZone;
/**
* <tt>Timestamp</tt>: A type that maps an SQL TIMESTAMP to a Java
* java.util.Date or java.sql.Timestamp using UTC time zone.
*/
public class UTCTimestampType extends org.hibernate.type.TimestampType {
@Override
public Object get(ResultSet rs, String name) throws SQLException {
return rs.getTimestamp(name, createUTCCalendar());
}
/**
* Creates UTC calendar. DO NOT USE a static calendar instance.
* This may lead to concurrency problems with (at least) the Oracle DB
* driver!
* @return Calendar with UTC time zone.
*/
private static Calendar createUTCCalendar() {
final Calendar c = Calendar.getInstance();
c.setTimeZone(new SimpleTimeZone(0, "UTC"));
return c;
}
@Override
public void set(PreparedStatement st, Object value, int index)
throws SQLException {
Timestamp ts;
if (value instanceof Timestamp) {
ts = (Timestamp) value;
} else {
ts = new Timestamp(((java.util.Date)value).getTime());
}
st.setTimestamp(index, ts, createUTCCalendar());
}
}
Use it as follows with Java annotations (you could use the type class also in a XML configuration file):
import java.util.Date;
import org.hibernate.annotations.Type;
@Entity
@Table(name="...")
public class Data {
private Date receptionTimeDt;
@Type(type="ch.meteoswiss.commons.hibernate.UTCTimestampType")
@Column(name="RECEPTION_TIME_DT", nullable=false)
public Date getReceptionTimeDt() {
return receptionTimeDt;
}
}
Of course, this mapping class only works with Hibernate and is not standard JPA.
Original post: http://peter-on-java.blogspot.com/2012/04/reading-and-writing-utc-timestamps-to.html