-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JPA next should support Java 8 Date and Time types #63
Comments
@glassfishrobot Commented |
@glassfishrobot Commented |
@glassfishrobot Commented
|
@glassfishrobot Commented
|
@glassfishrobot Commented |
@glassfishrobot Commented |
@glassfishrobot Commented |
@glassfishrobot Commented [1] http://www.postgresql.org/docs/9.3/static/datatype-datetime.html#DATATYPE-INTERVAL-INPUT I believe that interval is an ANSI SQL standard type |
@glassfishrobot Commented
This year must be also a leap year. Sadly, Date.valueOf(MonthDay.of(1, 1).atYear(0)) becomes "0001-01-01", so it can't be 0. |
@glassfishrobot Commented |
@glassfishrobot Commented |
@glassfishrobot Commented One could say, that predicate is "being essential" or "being of common use", but who defines what "essential" or "common use" is? See, for some applications, support for java.awt.Image and java.net.URL might be much more essential than support for LocalDate or ZonedDateTime. On the other hand, other applications might be full of LocalDate but never uses Instant. So where exactly to make the cut? This becomes particularly complex when looking at the sheer amount of types found in the JRE, and it is obvious there has to be a cut somewhere. Even JavaFX, which is bundled with the JRE, does not support Instant still in v8, so why should JPA? And looking at the current progress of Project Jigsaw, possibly the qualifying predicate might simply be answered by "all types in a particular jigsaw module"? Anyways, it is not up to me to decide. I do support your request, and would love to see support for rather all Java Time API times, particularly for Instant and Duration, and your request has prominent supporters like for example Java Champion Arun Gupa as I learned recently. But I doubt the final answer will be as simple an satisfying as we would love to have it. Maybe it would be better to simply set up another JSR, like "Common Data Type Conversions for the Java Platform", which provides much more mappings than just date and time, but also would not be bound to JPA but also could be used by JAXB, JAX-RS, and possibly more API that deal which the problem of transforming " to "? Having such a vehicle would really reduce boilerplate a lot. |
@glassfishrobot Commented
I'm not sure. Firstly currently the RI explodes with a ClassCastException when trying to write an attribute converter mapping a java.util.Calendar database value. Secondly the spec would have to say that when mapping a java.util.Calendar the time zone of the value returned from the database is the time zone of the value on the database instead of the time zone of the Java virtual machine (like java.sql.Date). JDBC only allows to access the time zone of a value using the Java 8 Date and Time API. |
@glassfishrobot Commented |
@glassfishrobot Commented |
@glassfishrobot Commented
I don't see how to achieve this with JPA as is. Until yesterday I have been using an AttributeConverter like this, based on code that can be found on several blogs:
I now realise that although this seems to work, it is wrong, because both Timestamp.valueOf() and Timestamp.toLocalDateTime() interpret the value as though it were in the default time zone, so the code breaks during daylight saving changeover when there's an hour of time that doesn't "exist" in the default time zone. For example, consider the test value 2016-10-02 02:02:01, which is a perfectly valid time when interpreted as UTC, but which does not exist in my local time zone (Australia/Sydney). If I (with default time zone Australia/Sydney) use the above converter to persist the LocalDateTime value LocalDateTime.of(2016, 10, 2, 2, 1, 0), the value is sent to the database, and stored, as '2016-10-02 03:01:00.0', and when it is read back into a LocalDateTime, its value is now one hour out! (I've done exactly this test to confirm.) My converter is now like this:
but this doesn't work as is; it requires the recently-added Hibernate-specific configuration (explained at http://in.relation.to/2016/09/12/jdbc-time-zone-configuration-property/) to specify using UTC when sending Timestamp values through JDBC:
So, although LocalDateTime values are "in theory" separate from concerns about time zones, it seems that when it comes to persisting them as Timestamp values, the values must be interpreted as being in some time zone. So, please consider providing some way of specifying that LocalDateTime values are persisted in a "transparent" way (avoiding all internal time zone conversions along the way), or, if that is not possible, specifying the time zone in which LocalDateTime values are to be interpreted. |
@glassfishrobot Commented Since you're using Hibernate I would normally recommend you use a UserType instead of an AttributeConverter since it gives you direct access to the PreparedStatement and ResultSet. If the driver supports JSR-310 data types you can use them natively without converting. Unfortunately Connector / J currently converts through java.sql types which still leaves it vulnerable to the issues you observed. Until this issue is fixed I would recommend you:
|
@glassfishrobot Commented
But I wouldn't (and I don't). As I wrote:
So I would have – following the values in your example – two LocalDateTime values LocalDateTime.of(2017, 4, 1, 15, 50, 0) and LocalDateTime.of(2017, 4, 1, 16, 10, 0). And I would want those to be persisted in my database, in columns of type DATETIME, as the values '2017-04-01 15:50:00' and '2017-04-01 16:10:00'. And when they are read back in, they are converted back into the original LocalDateTime values. And with the combination of:
this is the behaviour I get. I think I do not actually need a "solution" to my problem: I now seem to have one that works. The point of my first message is that the particular combination of the five dot points at the top of the message seems not to be currently achievable with "pure" JPA (i.e., without Hibernate-specific settings). You have mostly offered both non-alternatives (e.g., setting the JVM's timezone to UTC, which, at least for now, I can not do), and alternatives that also do not use "pure" JPA! I do thank you for suggesting to have a look at ZonedDateTime and OffsetDateTime. From a modelling point of view, these two classes allow modelling the fact that the values in my program do belong to a particular time zone (i.e., UTC). So, if you don't like my use of LocalDateTime, I now present the original problem, modified to use ZonedDateTime. I want a solution that has all of these features:
And again: I don't see how to achieve this with JPA as is. Here is the converter class using ZonedDateTime:
And again, this doesn't work as is, for the same reason as before: the converted Timestamp values are persisted in the local time zone, not in UTC. The Hibernate-specific setting hibernate.jdbc.time_zone=UTC is still required to make it work. I conclude: the Hibernate-specific property hibernate.jdbc.time_zone=UTC does actually solve a problem; it is not "syntactic sugar" for something you can do another way in "pure" JPA. So maybe it boils down to: please add a JPA setting that achieves what hibernate.jdbc.time_zone=UTC does. And maybe consider making the application of the setting scope-able (e.g., to individual fields). |
@glassfishrobot Commented
and in this case your code works as long as everybody remembers that in your application for your entities LocalDateTime means UTC. Once somebody writes
instead of
it breaks. The last converter you posted fixes this. |
@glassfishrobot Commented &serverTimezone=UTC&useLegacyDatetimeCode=false otherwise you "fall at the last hurdle" (i.e., the JDBC driver ruins everything when it converts Timestamp values to strings). Other databases may require something similar. |
@glassfishrobot Commented |
@lukasj Commented |
@lukasj Commented |
|
guys i need UTC instant for my backend, Come on! |
Currently, JPA temporal fields are supported for the following data types: java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, and java.sql.Timestamp. java.sql.Date properties are always mapped to the JDBC methods getDate and setDate, and it is an error to specify the @javax.persistence.Temporal annotation for these types. The same is true of Time (mapped to getTIme and setTime) and Timestamp (mapped to getTimestamp and setTimestamp). Properties of type java.util.Date and Calendar must be annotated with @TeMPOraL to specify the javax.persistence.TemporalType enum indicating which JDBC methods should be used for those properties.
Some vendors support other temporal types, such as Joda Time, but this is non-standard and should probably remain so since Joda Time isn't guaranteed to stay around (and, in fact, is likely to start ramping down with the release of Java 8).
JSR-310 as part of Java 8 specifies a new Date & Time API in the java.time package and sub-packages that supplants java.util.Date, Calendar, java.sql.Date, Time, Timestamp, and Joda Time. It is based off of the Joda Time API, but with enhancements and certain redesigns that the Joda Time founder/creator has said makes it superior to Joda Time.
JPA's existing rules for the currently-supported temporal types should remain largely unchanged. However, the specification should be added to in order to specify support for JSR-310. These are the proposed new rules I believe should be present in the JPA.next specification:
The text was updated successfully, but these errors were encountered: