I have a mySQL db with columns of the time type. I'm using Hibernate for ORM. The Hibernate time type is java.sql.Time. I'm noticing that whenever I update a column in the table, the time value also gets updated. The UTC offset gets added for every update. For example, consider a table with a name(string) and a time field. Let the initial db entry for time be "00:00:00". Now if I update name using an endpoint + Hibernate query, the time value gets updated to "05:00:00" in the db. If I update name again, the time value becomes "10:00:00" in the db. My time zone is EST by the way. Why is this happening and how can I prevent it?
Setting hibernate.jdbc.time_zone: UTC fixes the problem but I'd like some more information behind this behavior.
Have you Tried tot User LocalTime instead of java.sql.Time?
LocalTime should handle all the TimeZone pitfalls foe you.
Java.sql.Time is not TimeZone aware.
Related
I have encountered problem in using JPA to save Time type into database.
Time value from browser into Java is mapped correctly, but when JPA save the value into DB, it become a different value.
Is there any solution to save time into database without changing the data of time?
(I have only 2 solutions: Change Time type into long or string, but I still prefer the solution that can save Time value).
Data input in browser:
Data input in browser
Save before save into DB:
Data before save into database
The data save into database(I use MySQL). I change value from 11:00:00 to 04:00:00:
Data when save into database
Actually you are trying to use timestamp (which actually represents a time point) field for duration (which represents time interval) purposes.
When you enter 11:00 it might means 11:00 at PST, UTC, ICT timezones. And these will be absolutely different values.
Instead of java.util.Date in java you have to use java.time.Duration and use TIME field in MySQL (http://www.mysqltutorial.org/mysql-time/)
I using jpa and using jpa custom query excute method. I using TypedQuery and Entity manage excute when i write query. My Jpa excute look like :
String query = "select s from Student s where (b.beginDate + b.beginTime) < CURRENT_TIMESTAMP";
But when i excute it, it wrong when i select. It differs up to 2 hours
I have 2 question:
When i excute it, CURRENT_TIMESTAMP get database time, server
containing database or server running java machine. Because I have 2
servers. A server contains a database with a Paris time zone and a
server running spring with a JDK containing a Japan time zone.
When I create it, I want format CURRENT_TIMESTAMP as 'YYYY-MM-DD HH:Mm:SS'
Please help. Thanks
Your problem has nothing todo with JPA !
In Postgresql documentation it is written
The PostgreSQL CURRENT_TIMESTAMP() function returns the current date
and time with time zone, which is the time when the transaction
starts.
The TimeStamp returned is always a data and time WITH TIME ZONE.
In your SELECT the comparison will work if you have previously saved a time in same format.
If you have a field BEGIN_DATE_TIME with correct format, no problem.
You have certainly a problem because (b.BEGINDATE + b.BEGINTIME) will not produce a date and time with time zone value !
Can you give us more information about these 2 fields ?
I am trying to understand how to store an Unix timestamp (that is, a number of seconds since 1970 expressed in the UTC/GMT timezone) inside an HSQLDB embedded file database. However, I have yet to understand how TZ handling works with HSQL.
My program will be used from different zones, so using UTC is a must. Moreover, I cannot change the default time zone (as with java.util.TimeZone.setDefault) as it will be embedded in other programs and therefore should not change the environment.
My attempt - the doc states:
When datetime values are sent to the database using the PreparedStatement or CallableStatement interfaces, the Java object is converted to the type of the prepared or callable statement parameter. This type may be DATE, TIME, or TIMESTAMP (with or without time zone). The time zone displacement is the time zone of the JDBC session.
So I use a TIMESTAMP column inside the database (without time zone - the default), and issue SET TIME ZONE INTERVAL '0:00' HOUR TO MINUTE (to put the session in UTC TZ) and then INSERT INTO TEST VALUES(?) with ? being a Java Timestamp object containing the correct Unix value (GMT related, tested OK).
Sadly, in this case, the SQL log of the database shows the timestamp has been reverted back to my local time zone (+2). For a timestamp of 1442132237635 (8H17 in UTC, 10H17 in +2), we get TIMESTAMP'2015-09-13 10:17:17.602000' in the log. Wrong result... it seems changing the session time zone has absolutely no impact whatsoever (I've tried +14, -14... no changes). The SET order is however correctly executed - it appears in the SQL log, and the value of TIMEZONE() changes afterwards.
Other attempts
I've also tried to use a TIMESTAMP WITH TIME ZONE column, without setting the session TZ. In that case, the database stores 'local time +2', and I can extract the correct timestamp from it. This is borderline ridiculous - it means the HSQLDB driver takes the Java timestamp (UTC), interprets it correctly as UTC, casts it to the JVM default TZ then sends that to the DB. I don't want the TZ info in the DB - don't need it. (of note: changing the session TZ has no impact - the SQL order issued is always with my local TZ... makes you wonder what is the point of the SET TZ order)
And changing the default JVM TZ to UTC works but as stated above I cannot do that.
Also of note: this question seems related but the provided answer is basically to hack every SQL order which i would like to avoid...
My question
How can I simply store my UTC Java timestamp inside HSQLDB? And what is the purpose of the SET TIME ZONE order?
Thanks for reading.
Your first attempt is correct and will return the correct results.
Your database is located in UTC+2 time zone. You are connecting as if you were a remote user in the UTC time zone.
The log storage of the timestamp is not wrong as you claim. Log storage is not for the user of the database to read. The database stores its log in your location's time zone. Next time it reads the log it reads and interprets it according to your database time zone (nothing to do with the session time zone). Therefore the time stored in log as 10:17 will be 8:17 in UTC.
With TIMESTAMP WITHOUT TIME ZONE, the database files cannot be moved to a different time zone, as the timestamps will be interpreted according to the new location's zone.
The role of the SET TIME ZONE statement is to allow the correct adjustment when the data is stored. It does not change previously stored data. Naturally if a time is stored as 8:17, it should be read as 8:17 whenever and in whichever zone it is accessed.
For best portability use TIMESTAMP WITH TIME ZONE. The way it stores and retrieves the data is correct even if you move the database files.
User inputs date from JSP page, and it converts to Joda DateTime, the string output is
2014-03-26T00:00:00.000+09:00
However when I persist this entity containing date filed in database, and retrieve and print out again, it becomes
2014-03-25T09:00:00.000+09:00.
I don't know why database make this change to minus one day.
I use postgres, hibernate JPA for application development.
Thanks in advance.
What is the value in the database? Use pgAdmin app, the psql command line tool, or some other database admin tool to query Postgres directly.
What data type are you using in Postgres? You probably should be using TIMESTAMP WITH TIME ZONE. Avoid using the WITHOUT time zone type as it ignores any time zone offset info you may provide.
Despite the name, neither type stores any time zone info. The difference is whether you want Postgres to pay any attention to time zone info on incoming data. Be sure to read the doc thoroughly and play with it to experiment until understand how date-time works.
Read Always Use TIMESTAMP WITH TIME ZONE by David E. Wheeler, a Postgres expert.
It seems (and maybe I'm wrong) that if you want to preserve the timezone of when something happened with JDBC and Postgres you need to store the timezone separately from the timestamp.
That is I would prefer to give my ORM/JDBC/JPA a Java Calendar (or Joda DataTime) with say timezone America/New_York to a Postgres timestampz field. AND I would expect on retrieval regardless of the Servers timezone (or defaulting to UTC) to give me back a Calendar with timezone America/New_York. But just looking at most JDBC code (and things that depend on it that doesn't happen).
Is this correct?
This seems ridiculous that I would need to store the tz in another field when postgres supports it.
Thus it seems like the only two options are:
Select the timestampz Postgres column as a java.util.String and parse it.
Store the timezone as a separate field.
Option number one and two one would require some sort of conversion interceptors for my SQL mapping / ORM libraries.
What is the best solution for JDBC ?
What is the best solution for JPA (if different than JDBC)?
When you store a timestamp with time zone (timestamptz) it's converted to UTC for storage in the DB. When retrieved, it's converted to the client's current timezone, not the timezone it was originally in. It's a point in time, basically.
There is also timestamp without time zone (timestamp). This is not subject to conversion, but does not carry a timestamp with it. If you store a timestamp with your client time zone set to UTC, then retrieve it when the client time zone is '+08:00', you get the same value. That's half what you want, in that it preserves the raw time value.
The names and behaviours are awful and confusing, but set by the SQL standard.
You must store the time zone separately if you wish to record a point in time at a particular time zone. I'd recommend storing it as an INTERVAL with a CHECK constraint limiting it to be colname BETWEEN INTERVAL '-12' HOUR + INTERVAL '1' SECOND AND INTERVAL '12' HOUR. That definition rejects -12:00 and accepts +12:00; I'm not totally sure that's right, so check.
You could either store the timestamp of local time at that time zone (what I'd probably do), or store the timestamptz of the UTC time when the event occurred plus an offset that lets you convert it to local time.
Either will work fine for JDBC. For JPA, it'll depend on how well your provider understands and maps interval types. Ideally you want a transient generated field in your entity that reconstructs the Calendar instance you want using the timestamp and interval stored in the database.
EclipseLink supports storing the timezone in Oracle, I think you could get it to be stored in Postgres as well if you customized your PostgreSQLPlatform.