Query time column from postgresql using jdbc - java

I'm using PostgreSQL 8.4, and the server is linux, and the linux's time zone is'EDT' not 'UTC'. The configuration of PostgreSQL make the DataBase's time zone to 'UTC'. The code is running on JBoss9.
I have one sql, select to_char(ts_entry.submitted_date, 'MM/DD/YYYY HH24:MM') as submitted_date_format from ts_entry where ....
If we run the sql in PostgreSQL, we will get the value, "07/10/2017 02:07"
But when I try to get the value from resultSet in java,
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(sql);
String value = rs.getString("submitted_date_format");
The value will be "07/09/2017 22:07".
The origin value in DB is "2017-07-10 02:02:25.268+00".
How can I handle the effect caused by linux server's timezone in code level?
BTW, I know an alternative solution, change the start up scripts of jboss, to make the jboss to start up using timezone 'UTC'. Can this issue be handled in code level?

The Database server machine's time zone has no direct impact on the behaviour, except that it is used to initialize timezone in postgresql.conf, which is the initial setting for the client time zone unless overridden by the database session.
PostgreSQL stores timestamp with time zone in UTC internally and converts it to the client's local time zone upon delivery.
So you should set the database session time zone the way you need with
SET TIME ZONE '<time zone name>';
That will convert dates to that time zone when you select then from PostgreSQL.

Related

HQL query ignores time portion of the Date object

I have problem with HQL where I am setting the query parameters. One of them is Date. When I debug the code there is Date with time entering the method. I set the parameter using setParameter(timestamp, new Timestamp(date.getTime())) or query.setTimestamp...etc etc I used many combinations...
When I use p6spy to examine the SQL comming from app to the DB there is only '29-Jan-21' or other date without time.
I am using hibernate 5.1.0 final and postgre DB. I'll be glad for any help.
Example:
Query query = getSessionFactory().getCurrentSession().createQuery("SELECT user FROM UserEntity cr WHERE user.userStatus.id = :statusId AND :timestamp >= user.valid_to");
This is how I tried to set the timestamp parameter:
query.setParameter("timestamp", new Timestamp(date.getTime()));
query.setParameter("timestamp", date, TimestampType.INSTANCE);
query.setTimestamp("timestamp", date);
query.setTimestamp("timestamp", new Timestamp(date.getTime()));
Problem is that the generated SQL replace timestamp by '29-Jan-21' or other date I choose but without time. The date parameter comes to the method from UI and it contains full date with time.

MySQL/Hibernate retrieving wrong data with column mapped as LocalTime

I'm mapping a TIME column of a MySQL database in Hibernate (5.4.6.Final) as a java.time.LocalTime class.
This is the declaration of the mapping into the entity:
#Column(name = "TIMEVAL")
public LocalTime TIMEVAL;
The column in the database has value 00:30:00, however Hibernate it's building the instance of TIMEVAL with a value of 01:30:00.
I thought about a difference of time-zones (Ignoring the fact that the TIME data-type doesn't have a time-zone) between the server and the hibernate connection, but I setup each connection and the server as UTC.
And by executing the queries:
SELECT ##global.time_zone;
SELECT ##session.time_zone;
The result of the Hibernate session and the server were all +00:00.
Following the Hibernate configuration:
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
spring.datasource.url=jdbc:mysql://localhost:3306/..?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true
And here's the MySQL configuration:
default-time-zone=+00:00
I tried also:
Specifying the MySQL column as VARCHAR(8), but Hibernate always retrieves 01:30:00;
Changing the Entity data-type to Duration, but Hibernate throws an error saying that it can't map TIME to java.lang.Long.
What do I need to modify in order to have Hibernate build the LocalTime instance with the value of the database column?
As #Andreas pointed out in the comments. The JVM time zone wasn't in UTC.
I needed to change the JVM time zone to get the correct value out of the database.
So, by adding the following param to the JVM options:
-Duser.timezone=UTC
Finally the LocalTime instance was built with the value of 00:30:00 as the value of the database column.

Query with NOW() in criteria behaves differently in psql vs. JDBC

I am executing following query in psql via console and getting output :
select details
from history_transactions
,history_operations
where history_operations.transaction_id = history_transactions.id
and type = 3
and created_at >= NOW() - INTERVAL '5 minutes'
However when I call this code from my java program, it is not returning any output. The ResultSet is null. PFB my code:
Connection conn = getConnection();
java.sql.Statement stmt = null;
String sql ="select details from history_transactions , history_operations where history_operations.transaction_id=history_transactions.id and type =3 and created_at >= NOW() - INTERVAL '5 minutes'";
try{
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while(rs.next()) {
System.out.println("Inside resultset");
}
}
catch(Exception e)
{
e.printStackTrace();
}
Any idea where I am going wrong?
I am not getting any exception as well.
Note: If I change the interval from 5 minute to 6 hours or more it is working and giving me output. If I change the interval < 5 hours then the resultset is null. However If I login to psql server and execute the query as it is in the code. I am getting output.
I am using java version "1.8.0_151" and PostgreSQL JDBC 4.2 Driver, 42.2.1 - as per https://jdbc.postgresql.org/download.html - it is the suitable driver.
The PostgreSQL NOW() function returns a timestamp with time zone value. In order to use that value against a column of type timestamp (without time zone) PostgreSQL needs to implicitly CAST that value to match the column type. However, testing shows that if the client and the server are set to different time zones the result of that CAST can be different when connected via psql vs. when connected via JDBC. For example:
Server time zone: UTC
Client time zone: America/Denver, a.k.a. "MST/MDT", currently UTC-7
When connected via psql,
SELECT CAST(CAST(NOW() AS timestamp) AS varchar)
returns the UTC value
2018-02-05 22:40:25.012933
but when connected via JDBC the same query returns the MST value
2018-02-05 15:40:57.288587
To return the UTC value under JDBC we can execute
set time zone 'UTC'
before running our SELECT query.

JDBC PreparedStatement - setTimestamp does not save the time

I am trying to save a timestamp to a SQL DB with the following line inside a PreparedStatement
ps.setTimestamp(5, new Timestamp(ITEM.getModifiedTime().getTime()));
When I debug and inspect the PreparedStatement I can see the date and the time with the Java and SQL types being timestamp but when I look at the DB the field appears like this
2016-08-08 00:00:00.000
How can I get the time to come through? I am using SQL Server 2008

How is SQL Server's timestamp2 supposed to work in JDBC?

I'm having some trouble trying to use timestamp2 instead of Timestamp in SQL Server 2008. Apparently, rs.getTimestamp has very different behavior between timestamp and timestamp2. However, I can't find any documentation stating that there should be a difference, or that I should be using something different. I wonder whether I'm just doing something wrong.
Environment:
Tried on both SQL Express 2008 (10.0) and SQL Server 2008 R2 (10.5).
sqljdbc4.jar version 3.0, size of 537,303 bytes, CRC-32=a0aa1e25, MD5=402130141d5f2cee727f4371e2e8fd8a.
Java 1.6
Here is a unit test demonstrating the problem. The only "magic" is the "Db.getConnection()", which you can replace with appropriate code. The test is the same for both datetime and datetime2, but the datetime2 test fails with a date that is 2 days prior. I treat all times in the DB as GMT/UTC, and I haven't attempted to add timezone information into the database data for datetime2 data.
private void testTimestamp(TimeZone gmtTz, Connection conn, String query,
Calendar expectedCal) throws SQLException
{
PreparedStatement stmt = conn.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
while (rs.next())
{
// Note the expectedCal has a GMT timezone.
Date actualTs = rs.getTimestamp("dt", expectedCal);
// Just print out the time difference
long diff = actualTs.getTime() - expectedCal.getTimeInMillis();
System.out.println("Diff=" + diff);
// Do the test to make sure they are the same
// In practice, this succeeds for datetime and fails for datetime2
Assert.assertEquals(expectedCal.getTimeInMillis(), actualTs.getTime());
}
}
#Test
public void testDateTime() throws SQLException
{
Connection conn = Db.getConnection();
TimeZone gmtTz = TimeZone.getTimeZone("GMT");
String query;
Calendar expectedCal = Calendar.getInstance(gmtTz);
expectedCal.clear();
expectedCal.set(2011, 10, 02, 11, 17);
query = "select CAST('2011-11-02 11:17:00' as datetime) as dt";
testTimestamp(gmtTz, conn, query, expectedCal);
query = "select CAST('2011-11-02 11:17:00.0000000' as datetime2) as dt";
testTimestamp(gmtTz, conn, query, expectedCal); // results in an error
}
Is my only option switching back to timestamp?
EDIT: For future Googlers, using sqljdbc4.jar version 3.0, the test fails on Linux, but passes on Windows.
I have not yet tried sqljdbc4.jar version 4.0 that comes with SQL Server 2012.
If you are using Sun JRE 1.7 with the Microsoft JDBC 3.0 driver see this blog post http://blogs.msdn.com/b/jdbcteam/archive/2012/01/20/hotfix-available-for-date-issue-when-using-jre-1-7.aspx.
If you feel you have discovered a bug in our driver you can report it via Microsoft Connect.
https://connect.microsoft.com/SQLServer
I remember not hearing good things about the official SQL Server driver and JTDS being preferred (though I can't seem to be finding that link). I would personally go with JTDS (with rigorous testing of course) or move back to the version which doesn't cause an issue. I haven't worked with SQL Server but from the looks of, it seems that datetime2 is the preferred data type so I'd rather not revert back. Option (d) isn't really a good option IMO. :)

Categories

Resources