简体   繁体   中英

Is j.u.Calendar object immutable/thread-safe in PreparedStatement#setTimestamp, ResultSet#getTimestamp?

I'm performing some micro optimisations and have noticed that application constructs new juCalendar object on every call of ResultSet#getTimestamp or ResultSet#getTimestamp like:

Timestamp timestamp = rs.getTimestamp(name, Calendar.getInstance(UTC));

I tried to research whether it is possible to use singleton object and have discovered following:

  • H2 driver does not mutate calendar object and consumes the result of juCalendar#getTimeZone call
  • PostgreSQL driver behaves similarly to H2
  • Oracle driver copies juCalendar via Calendar.getInstance(cal.getTimeZone()) and mutates a copy

So, it seems that juCalendar could be a singleton in case of particular JDBC drivers, but is it true for all JDBC drivers, ie are there any specifications/recommendations for driver vendors?

The only thing the JDBC specification says is in the javadoc.

For PreparedStatement.setTimestamp (and similar for setDate and setTime ):

Sets the designated parameter to the given java.sql.Timestamp value, using the given Calendar object. The driver uses the Calendar object to construct an SQL TIMESTAMP value, which the driver then sends to the database. With a Calendar object, the driver can calculate the timestamp taking into account a custom timezone. [..]

For ResultSet.getTimestamp (and similar for getDate and getTime ):

[..] This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does not store timezone information.

Both describe the Calendar parameter as:

the java.util.Calendar object to use in constructing the timestamp

In other words, JDBC implementations are allowed to "use" the calendar object in any way they deem fit. Some JDBC implementations actually use this calendar instance to perform calculations, others just extract the time zone data and do their calculations in another way (including, but not limited to, creating a new Calendar instance).

In other words, do not assume that it is safe to reuse the Calendar object across multiple threads. Using it across multiple invocations in the same thread is probably safe, but even that could be a dangerous assumption (eg you may want to reset the time zone with setTimeZone ). However, it would be better to simply not use it at all, and instead switch to using LocalDateTime , which foregoes time zone manipulation, or - assuming the column is actually a TIMESTAMP WITH TIME ZONE , OffsetDateTime .

I would also be wary of making optimizations targeting the behaviour of a specific driver. If the implementation of the driver changes, you could suddenly be faced with a hard to diagnose issues like wrong timestamp values caused by race-condition/incorrect shared use of the Calendar .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM