tl;dr
- Use java.time classes rather than legacy date-time classes. Specifically,
LocalDate
for date-only value.
- Use placeholders in your SQL and prepared statement.
- Pass java.time objects directly, via JDBC 4.2.
Example:
myPreparedStatement.setObject( 1 , startLocalDate ) ;
myPreparedStatement.setObject( 2 , stopLocalDate ) ;
…and…
myResultSet.getObject( … , LocalDate.class)
java.time
With JDBC 4.2 and later, you can exchange smart objects with your database rather than dumb strings.
Placeholders
Set up your prepared statement using placeholders rather than literals.
String sql = "SELECT * FROM tbl WHERE fromCol >= ? AND toCol < ? ;" ;
LocalDate
Set up the values to fill-in those placeholders. For a date-only column such as SQL-standard type DATE
, use the java.time.LocalDate
class. The LocalDate
class represents a date-only value without time-of-day and without time zone.
LocalDate start = LocalDate.of( 2018 , Month.JANUARY , 1 ) ; // First of January 2018.
Half-Open
Generally best in date-time work to use the Half-Open approach to defining a span of time, where the beginning is inclusive while the ending is exclusive. So if you want the entire month of January, query for "is equal to or later than the first of the month AND is less than the first day of the following month".
LocalDate stop = start.plusMonths( 1 ) ; // First of February 2018.
Or, your intention might be more clear by using the YearMonth
class to represent the entire month as a whole.
YearMonth ym = YearMonth.of( 2018 , 1 ) ; // January 2018.
LocalDate start = ym.atDay( 1 ) ; // First of January 2018.
LocalDate stop = ym.plusMonths( 1 ).atDay( 1 ) ; // First of February 2018.
PreparedStatement
& ResultSet
Either way, we now have a pair of LocalDate
objects to feed into our prepared statement's placeholders.
myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;
When retrieving from the result set:
LocalDate start = myResultSet.getObject( … , LocalDate.class ) ;
Avoid the legacy date-time classes
No need for java.util.Date
, java.sql.Date
, or any of the other poorly-designed hack date-time classes bundled with the earliest versions of Java.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.