JPA + PostgreSQL: Only time being persisted - java

I have a PostgreSQL table containing a timestamp without time zone field. This is configured in my Java code as follows:
#Column(name = "timestamp")
#Temporal(TemporalType.TIMESTAMP)
private java.util.Date timestamp;
The timestamp property is being set to new Date() i.e. containing both the date and the time. However in the database the date part is not being persisted e.g. "14:40:28.889"; therefore when it is retrieved from the database the date is not loaded and set to default i.e. 01/01/1970. Any ideas where the date part of the timestamp is running off to?
UPDATE:
I increased the logging level for hibernate so I can see what is being persisted by adding the following in the application.properties file:
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
The log output was as follows:
binding parameter [6] as [TIMESTAMP] - [Wed Sep 16 08:57:03 CEST 2015]
UPDATE 2:
I stepped through the code and found the insert sql with the date formatted as 2015-09-16 11:16:09.416000 +02:00:00. I insert the string automatically in PGAdmin and it insert with no error. After save a clicked the little refresh button and the date part disappeared! So the data is being persisted correctly but somehow postgre is doing something weird afterwards.

This was one of the silliest mistakes ever, I had a script that creates the tables and it was marked as "time without timezone" i.e. not timestamp so PostgreSQL was obviously removing the date. I will leave this question as it might help someone debug similar issues.

Related

Two databases with the same data, are reporting different times

I live in Arizona, MST with no DST if it matters.
I have two different Oracle Databases, that is storing a list of holidays and weekends.
The column that stores the data is a DATE format, no time value.
But when I use the API to call the first db for holidays in Jan 2021, it reports the holiday date at midnight. But when I call for all holidays in Jan 2021 on the second db, it reports it as all holiday date as 7am.
The query that the db uses is
SELECT * FROM CLPUSER.HOL_DT WHERE TRIM(HOL_DT) >= ? AND TRIM(HOL_DT) <= ?";
The API is using Vertx-jdbc when calling the db. I have double checked the configuration of the API and the db, all are using MST.
Here are the values that are returned from the API call
DB1
"publicHolidayList": [
"holidayDate": "2021-01-01T00:00:00Z",
"holidayDate": "2021-01-02T00:00:00Z",
"holidayDate": "2021-01-03T00:00:00Z"
...
]
DB2
"publicHolidayList": [
"holidayDate": "2021-01-02T07:00:00Z",
"holidayDate": "2021-01-03T07:00:00Z"
...
"holidayDate": "2021-01-01T07:00:00Z" //appears at bottom
]
Edit: Just debugged through the code till I got to how vertx jdbc reads it from the underlining JDBC library, It is reading the HOL_DT from the jdbc as a TIMESTAMP, when the db stores it as a Date Format. When it does that, it converts to ZoneDateTime at UTC, giving its timevalue.
Turns out something was different. When redeploying the code in one the environments, it started to show the "2021-01-02T07:00:00Z" like the other. My working theory is that for some reason one of the pods was set to UTC time, but now at MST time.
Also, the whole one entry being out of order was due to it not having Sort by function, and when I inserted all of these in Oracle, I forgot the first entry and it got put to the end.
¯\_(ツ)_/¯

Java Date to SQL Server datetime2 via Hibernate: getting ms rounded like datetime?

My Java fields are defined as Dates, and like some others I have run into the issue of SQL Server's datetime rounding milliseconds strangely (to the nearest 1/300 sec). Accordingly, I changed my tables to datetime2(3) for proper ms precision. Why is the rounding still incorrect when Hibernate saves a value to the DB?
The value looks correct in the SQL insert statement, but by the time it gets to the DB it is wrong. For example, if I insert 2017-01-31 01:23:00.999...
during insert:
<BasicBinder>binding parameter [11] as [TIMESTAMP] - [Tue Jan 31 01:23:00 PST 2017]
from select shortly thereafter:
<BasicExtractor>extracted value ([start_t11_80_4_] : [TIMESTAMP]) - [2017-01-31 01:23:01.0]
I've tried specifying the dialect as SQLServer2008Dialect instead of SQLServerDialect. (I've also tried specifying a custom dialect overriding SQLServerDialect, where I register column types Types.DATE/TIME/TIMESTAMP to "datetime2".)
I've tried specifying columnDefinition="datetime2" in the #Column annotation for the Date getter.
What am I missing? I feel like it must be possible to do this without changing the Java fields from Date to Timestamp, and without changing the DB columns from datetime2 to long...

Java Retrieve date records in correct format from mysql

I have a table which was populated by a excel. The date in the columns shows according to my system's timezone when a select query is run in mysql.
But when i run the same query in java using jdbc connection, i am not getting the correct values as which was present in the excel.
I know it is a issue with the timezone. Please guide me with the changes that need to be done for the select query
Result of the following queries are NULL.
SELECT * FROM mysql.time_zone;
SELECT * FROM mysql.time_zone_name;
Just to elaborate on the issue, when i run a select query on date in mysql server, i get the right date values for a column. But when i run the same through a java program, i get converted values to a different timezone.
THe java code is as follows:-
resultList=(List<FosProd>)getEntityManager().createNativeQuery("select fe, count(ldcfe) as Ttlv, count(IF(ldcfe='PTP',1,NULL)) as PTP,DAY(ludfe) as dayte from (select FOS_NAME as fe,Last_Disposition_Code_FOS as ldcfe,Last_Updated_Date_FOS as ludfe from kic.master_mis group by ALLOCATION_DATE,ALLOCATION_BUCKET,BILLED_ID,CUSTOMER_NAME,TOTAL_OUTSTANDING) as s1 where monthname(ludfe)=\"NOVEMBER\" GROUP BY MONTH(ludfe), DAY(ludfe),fe;", FosProd.class).getResultList();
DAY function in SELECT is providing me converted values.
Please help.
public class FosProd implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Size(max = 50)
#Column(name = "fe")
private String fe;
#Basic(optional = false)
#NotNull
#Column(name = "Ttlv")
private long ttlv;
#Basic(optional = false)
#NotNull
#Column(name = "PTP")
#Id
private long ptp;
#Column(name = "dayte")
private Integer dayte;
Likely, it's the JDBC driver "helping" you out, altering the DATETIME/TIMESTAMP values because it's making adjustments to those values because of a difference in the timezone setting of the MySQL server and the JVM.
To see the timezone in effect for your connection to the MySQL server:
SELECT ##time_zone
Compare that to the timezone used by the JVM. If those are the same, then the JDBC driver shouldn't be making any adjustments to the values. If those are different, then it's likely that the JDBC driver is making timezone adjustments to the values.
Change JDBC Connection settings
We had to configure some options on the JDBC connection (MySQL J/Connector) url to stop the JDBC driver from doing brain dead timezone conversions, I think the most important change we made was:
useLegacyDatetimeCode=false
I think we also had to set noTimezoneConversionForDateType=true so timezone adjustments were't made on pure DATE datatypes.
I believe we also did some experimentation with custom mappings, between SQL datatypes and JDBC datatypes. But I don't think those ended up as part of our solution.)
(And obviously, this won't apply if you are using the MariaDB JDBC driver; we're just guessing that you're using MySQL J/Connector.)
NOTE: I'm not saying this is a solution to the issue being reported. The problem description provided in the question is very vague. There's no possible way for anyone to recommend a "solution" based on the information in the question.
Other approaches
That's not the only approach to addressing the issue, there are several other avenuesl suitability of these approaches really depends on your requirements, and what you are trying to achieve.
One "easy" button (probably not the most appropriate solution for you) would be to modify the timezone of the JVM to match the timezone of the MySQL server. BUT... that's going to impact a whole boatload more than just timezone adjustments made by JDBC Driver.
Another "patch" would be to not return DATETIME or TIMESTAMP expressions in the SELECT, but return expressions that have a character datatype instead. That will make the JDBC driver "bypass" any timezone adjustments is doing on DATETIME, (BUT... you'll be returning values that will be mapped into String, not Date or Calendar objects. e.g.
SELECT DATE_FORMAT(mydatecol,'%Y-%m-%d %h:%i:%s') AS mydate_string
FROM
In a similar vein, you could return the UNIX_TIMESTAMP(mydatecol), and that's going to return an integer (number of seconds since midnight Jan 1, 1970 UTC). The value return by that is going to be informed by the setting of the time_zone variable in the MySQL session.)
Again, that's likely not the most appropriate solution.
We assume that you are seeing the "correct" DATETIME values when you run a query against the MySQL server. What's most important here is knowing the setting of the time_zone variable in your MySQL session.
SELECT ##time_zone

Setting Date and Time into Oracle Date field using ebean

Good old date/time problem which I can't to solve with good style...
DB: Oracle 11g
Table contains field: upd_date with Oracle type DATE - I can't change it to TIMESTAMP
My Ebean model:
#Column(name="UPD_DT")
public Timestamp uploadedAt;
I'm trying to save model with current timestamp and then check which value has been saved:
model.uploadedAt = new Timestamp(System.currentTimeMillis());
model.save();
System.out.println("Time before save:" + model.uploadedAt);
System.out.println("Time after save:" + Models.byId(model.id).uploadedAt;
And getting following results:
Time before save:1391633542210
Time after save:1391633542000
I'm know that the difference in these fields because of Oracle DATE doesn't have milliseconds part, but if I will try to update this model object without changing uploadedAt field - I will get: javax.persistence.OptimisticLockException: Data has changed.
Is there any correct way to declare fields in JPA models for Oracle Date field with date and time included, when I don't need to change TimeSpamp every time when I want to update object?
P.S. : Creation like new Timestamp((System.currentTimeMillis()/1000)*1000); looks ugly and all others solution with cutting milliseconds in TimeStamp are very heavy.
I'm trying to find short and clear solution when I don't need to think about superfluous milliseconds.

hibernate criteria for a time range search on a Date field

Im using Oracle 10g,Hibernate 3,springMVC, jqgrid. I have some Date fields in ORACLE which are mapped as follows
#Temporal(TemporalType.DATE)
#Column(name = "DOC_CREATION_DATE", length = 7,insertable=true,updatable=false)
public Date getDocCreationDate() {
return this.docCreationDate;
}
In my grid I filter date using jqueryCalendar and everything is fine. now I have a new request from the client which is to show the time of documentCreation and they also want to be able to filter by a time range. for example:
find all records created between 6:am and 7:pm, find all records created at 6:am.
I have tried already formatting the date field with
#Temporal(TemporalType.TIMESTAMP)
and that's not what they want
Is there any other approach to this problem, any good ideas how to implement this are very welcome.
the thing is I need to use the same mapped field to query in one column of the Jqgrid for the regular date(12/01/2012 using jqueryCalendar)and add another column for the time part of that same mapped field once that is done I need to query (hibernate criteria) the time column for a range of time
something like this mock:
...
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart",6AM ));
thank you for all the help
The column is of type mapped to a Time, and thus you must compare its value with a Time:
Time sixAM = Time.valueOf("06:00:00");
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart", sixAM));
You can also use a regular date:
Date sixAM = new SimpleDateFormat("HH:mm").parse("06:00");
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart", sixAM));
You must change the #Temporal annotation to use either TemporalType.TIMESTAMP or add another field and annotate it with TemporalType.TIME. Hibernate uses the #Temporal annotation to determine if the field is to be treated like a java.sql.Timestamp or a java.util.Date with the time lopped-off (set to midnight, or 00h 00m 00.0s). This allows developers to use java.util.Date everywhere in their application and never have to worry about the Timestamp class (it's banished from most of our codebase).

Categories