// you're reading...

EJB3 JPA: Dealing with Date, Time and Timestamp

Today, I feel the urge to document this. Yes, even though there had been ways which databases and Java JDBC driver/Persistent engines deal with Date, Time, DateTime, Calendar, Timestamp and whatever database data type or Java class types that represent dates and time and even time zone had long been there since the very beginning, but still many developers are often confused with how to persist fields that represents date, time, date-time or timestamp through EJB3/JPA. So, this article is mainly about 3 very simple ways that we could achieve this.


I have to first admit that I am no expert in the scientific facts of representation of dates and time in the java.util.Date or java.util.Calendar class. But I do believe that by simply being able to understand a few characteristics of all these date and time related data types, whether if it is database specific or in terms of Java class types, it could definitely help you to develop applications/systems that are correct and accurate.

In this article, I want to show you three ways to code your EJB3/JPA Entity class when it comes to properties that deal with date, time, date-time and timestamp, by using a database table structure below in MySQL DB:

This “DATEANDTIMESTUFF” table is a simple table that captures fields of different DATE, TIME, DATETIME and TIMESTAMP data in the MySQL database. We’ll be using this table as a reference to the below Java JPA persistent class fields.

Method 1: Data Type Representation Using java.sql.Date, java.sql.Time and java.sql.Timestamp

@Column(name = "DATE_FIELD")
private java.sql.Date dateField;
    
@Column(name = "TIME_FIELD")
private java.sql.Time timeField;
    
@Column(name = "DATETIME_FIELD")
private java.sql.Timestamp dateTimeField;
    
@Column(name = "TIMESTAMP_FIELD")
private java.sql.Timestamp timestampField;

You can always represent date, time and timestamp field with the specific java.sql.Date, java.sql.Time and java.sql.Timestamp data type class. Do take note that these classes will store only the value of the date, time and datetime together, without any information on the geographical location, region, Greenwich Mean Time Offset (e.g. GMT-8:00, etc.) or any other extended date and time details.

When Should You Use Method 1?

If your application only requires to store date and time values, without the need to store extended detail of dates and time like server GMT offset or storing different date and time in different region or time zone, this method is sufficient for most.

 

Method 2: Date, Time and Timestamp Representation Using java.util.Date

@Temporal(TemporalType.DATE)
@Column(name = "DATE_FIELD")
private java.util.Date dateField;
    
@Temporal(TemporalType.TIME)
@Column(name = "TIME_FIELD")
private java.util.Date timeField;
    
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DATETIME_FIELD")
private java.util.Date dateTimeField;
    
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "TIMESTAMP_FIELD")
private java.util.Date timestampField;

Since the java.util.Date class could store both date and time information, we need to have an extra @Temporal annotation with the correct TemporalType attribute (TemporalType.DATE, TemporalType.TIME or TemporalType.TIMESTAMP). In the Java EE API documentation, it was written that the @Temporal annotation will map the java.util.Date or java.util.Calendar data type as java.sql.Date, java.sql.Time or java.sql.Timestamp. But here when using MySQL as the database, I happen to discover that persisting the field as java.sql.Time is rather different as compare to persisting the field as java.util.Date with @Temporal(TemporalType.TIME). The result goes like this:

If you persist as java.sql.Time into the DB, retrieve it, convert the data back to java.util.Date and print out the values by toString() method, the date is always kept at 1970 Jan 1.

However, if you persist the property field as java.util.Date with @Temporal(TemporalType.TIME) into the DB and do the same thing by retrieving it and print out the values by toString() method, the date will be the date when the data was persisted.

So, do watch out of this very minor difference/behavior, which might cause inconsistency in result expectation depending on your application.

When Should You Use Method 2?

Referring to the above stated behavior, use Method 2 when you need to store the server/application’s date and GMT values with the date, time or timestamp field, if that it is necessary.

 

Method 3: Date, Time and Timestamp Representation Using java.util.Calendar

@Column(name = "DATE_FIELD")
@Temporal(TemporalType.DATE)
private java.util.Calendar dateField;
    
@Column(name = "TIME_FIELD")
@Temporal(TemporalType.TIME)
private java.util.Calendar timeField;
    
@Column(name = "DATETIME_FIELD")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Calendar datetimeField;
    
@Column(name = "TIMESTAMP_FIELD")
@Temporal(TemporalType.TIMESTAMP)
private java.util.Calendar timestampField;

The same as java.util.Date data type, if a field is represented as java.util.Calendar, it will require the @Temporal annotation with the TemporalType attribute specified.

When Should You Use Method 3?

Method 3 is very suitable especially if you need to store date, time or datetime data with reference to different region, timezone or geographical details. The java.util.Calendar class is one of the most flexible and highly powerful class to capture dates and time with lots of manipulations.

Therefore, if you are developing application which requires international date and time information capturing, java.util.Calendar class as the property field data type is the preferred choice.

Summary

I highly suggest that you experiment the values with different data types against different databases to see the behavior of the persisted data, by persisting, retrieving and converting the data. Do also perform a “SELECT…ORDER BY…” SQL statement to see if the results are according to your requirements and expectation.

Hope this helps.

Related Articles

Previous Posts

Java LDAP/JNDI: 2 Ways Of Decoding And Using The objectGUID From Windows Active Directory

Java LDAP/JNDI: 2 Ways Of Decoding And Using The objectGUID From Windows Active Directory

October 13th, 2012

Windows Active Directory is a good way for many corporations to be used as a means of user managemen[...]

Quick Note: Unable To Perform LDAP Wildcard “*” Search On Windows Active Directory

Quick Note: Unable To Perform LDAP Wildcard "*" Search On Windows Active Directory

October 9th, 2012

In case you are searching high and low for a solution or an answer to why Windows Active Directory d[...]

Java JNDI/LDAP: Windows Active Directory Authentication, Organizational Unit, Group & Other Information Access

Java JNDI/LDAP: Windows Active Directory Authentication, Organizational Unit, Group & Other Information Access

October 4th, 2012

In today's IT environment, most mid-size corporation and above will have some form of centralized em[...]

MySQL Cluster NDB 7.2 on Solaris 10 Part 3 – Testing The Cluster

MySQL Cluster NDB 7.2 on Solaris 10 Part 3 - Testing The Cluster

September 22nd, 2012

We are back again to have fun with our cluster that we've setup written in our previous articles on [...]

MySQL Cluster NDB 7.2 on Solaris 10 Part 2 – Starting, Distributed Synchronized Users Management And Stopping The Cluster

MySQL Cluster NDB 7.2 on Solaris 10 Part 2 - Starting, Distributed Synchronized Users Management And Stopping The Cluster

September 18th, 2012

This is the continuation from the previous part of the tutorial MySQL Cluster NDB 7.2 on Solaris 10 [...]

MySQL Cluster NDB 7.2 on Solaris 10 Part 1 – How To Install, Setup and Configure

MySQL Cluster NDB 7.2 on Solaris 10 Part 1 - How To Install, Setup and Configure

September 18th, 2012

If you have landed on this page, we believe you might either had a bumpy ride in getting the MySQL c[...]

Quick Fix: How to Solve “Unable to read the logging configuration” on Netbeans7 with JBoss6

Quick Fix: How to Solve "Unable to read the logging configuration" on Netbeans7 with JBoss6

September 8th, 2012

This is just a quick fix post for those whom are having this problem when running JBoss 6.x with Net[...]

Making sense of EJB3.x Transaction Attributes – Part 4 (NEVER)

Making sense of EJB3.x Transaction Attributes – Part 4 (NEVER)

September 5th, 2012

This is the last part in the series of "Making sense of EJB3.x Transaction Attributes". So far, we'v[...]

Making sense of EJB3.x Transaction Attributes – Part 3 (Difference Between SUPPORTS and NOT_SUPPORTED)

Making sense of EJB3.x Transaction Attributes – Part 3 (Difference Between SUPPORTS and NOT_SUPPORTED)

September 5th, 2012

Oracle had extensively documented the behavior of each transaction attributes in the Java EE documen[...]