java.sql.Date in Java 8 compared to Java 6 java.sql.Date in Java 8 compared to Java 6 oracle oracle

java.sql.Date in Java 8 compared to Java 6


While I do not have an explanation, except to say many folks have reported problems and violations of JDBC with the latest generations of Oracle drivers, I can say that you are misusing those classes. And better classes are available.

java.sql.Date is date-only

You have selected the wrong class on the Java side. While the java.sql.Date class does indeed have a time set to 00:00:00 in UTC within its internals, you are supposed to ignore that fact, as instructed by the class documentation. The java.sql.Date is intended for a date-only value, without a time-of-day and without a time zone.

This class is a poor design, a bad hack, inheriting from java.util.Date while telling you to ignore that inheritance fact.

java.sql.Timestamp is date and time

The java.sql.Timestamp is the type you need in your case rather than java.sql.Date. (But read on for an even better class.)

The whole bunch of old date-time classes from the earliest versions of Java were a brave industry-first attempt at tackling the problem of date-time handling, but they fell short. They are poorly designed, confusing, and troublesome. Avoid them: java.util.Date, java.util.Calendar, java.util.GregorianCalendar, java.text.DateFormat, java.text.SimpleDateFormat. And if possible, avoid the java.sql types as well. Instead use the java.time classes.

JDBC 4.2

As of JDBC 4.2, your JDBC driver may be able to directly access java.time types from your database. The PreparedStatement::setObject and ResultSet::getObject methods may be able to render your date-time values from the database as java.time objects.

Instant instant = myResultSet.getObject( 1 );

…or perhaps…

Instant instant = myResultSet.getObject( 1 , Instant.class );

If your driver is not so capable, then convert briefly to the java.sql types and immediately convert to java.time yourself. Do all your business logic using java.time. Resort to java.sql types only for exchanging data with the database. To convert to/from java.time, look for new methods added to the old classes. For example, java.sql.Timestamp::toInstant.

Here we extract a java.sql.Timestamp from the ResultSet and immediately convert it to an Instant. You may want to do this on two lines instead of one combined line for debugging purposes.

Instant instant = myResultSet.getTimestamp( 1 ).toInstant();


Java SE 8 also has classes for some other common use cases.

YearMonth

There is the MonthDay class, which contains a month and day. Useful for representing birthdays.

MonthDay

The YearMonth class covers the credit card start date and expiration date use cases and scenarios in which people have a date with no specified day.

JDBC 4.2

JDBC in Java SE 8 will support these new types, but there will be no public JDBC API changes. The existing generic setObject and getObject methods will be sufficient.