java.sql.Timestamp error when inserting into DATETIME - java

When I try to use a java.sql.Timestamp value to insert into a DATETIME column in MySQL 5.6, I always get this error:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: '' for column 'invoice_date' at row 1
The original developer of this project had custom JARs that created the Prepared statements, such that java.util.Date is converted into Timestamp to be inserted into DATETIME and vice versa, as well as handled database connections. Note that this is my assumption since there is no documentation about it. Trying to use a timestamp to insert into DATETIME myself via PreparedStatement had the same results, using something like:
ps.setTimestamp(3, new Timestamp(date.getTime()));
I had to create my own connection so that I can use java.sql.Date to solve this problem. However it zeroes the time value as a result. I used
ps.setDate(3, new java.sql.Date(date.getTime()));
And I get something like
2013-06-27 00:00:00
in the table, since as we know java.sql.Date doesn't store the time.
Surprisingly, on a server that uses MySQL 5.0, this works normally. I'm assuming the millisecond value in Timestamp is causing the problem casting into DATETIME? Since the original works in older versions. Is there any way to resolve this without having to reinstall everything with 5.0?

If the problem is milliseconds, explicitly date format your timestamp. If the use case succeeds on MySQL 5.0 and you have different jdbc drivers deployed on 5.0 and 5.6, it is worth testing that driver over MySQL 5.6. Finally, you are not passing an index in your setters and the incorrect datetime value is the empty string. Have you verified in a debugger/logs that you are not attempting to insert an empty string?

Related

Jooq is adjusting timestamptz to instant conversion using JVM timezone

I have a book record in my postgres database, with the displayTimestamp (of type TIMESTAMPTZ) set to 2020-04-01T15:19:35.511599Z. The database timezone is set to UTC.
When I query with jooq (TIMESTAMPTZ converted to java.time.Instant), such as:
jooq.select(Books.BOOKS.DISPLAY_TIMESTAMP)
.from(Books.BOOKS)
.fetchOne()
I get the correct value, 2020-04-01T15:19:35.511599Z.
However, when I query using the jooq trunc method:
jooq.select(trunc(Books.BOOKS.DISPLAY_TIMESTAMP))
.from(Books.BOOKS)
.fetchOne()
I get the result of 2020-03-31T22:00:00Z. The timestamp seems to be -2 hours from the expected value. I notice that when I set the JVM timezone explicitly via -Duser.timezone=UTC, the problem is fixed.
This shows that JOOQ is making an adjustment to the timestamp based on the JVM's timezone, but weirdly only when using the trunc method.
Can anybody offer any input on fixing this? Ideally I would like JOOQ (3.13.0) to not make any adjustment based on the JVM timezone.

How to fix Cannot parse "DATE" constant issue in H2 Database?

I am porting my Java application which was developed for Windows to AIX Unix. On Windows it uses SQL Server for configuration. On AIX we are trying to use H2 database. Most of the code works but I am getting following error when executing query which has a datetime criteria.
org.h2.jdbc.JdbcSQLDataException: Cannot parse "DATE" constant "26-Jun-2019"; SQL statement:
SELECT EM_SCHEDULER_DAILY_POLL.* FROM EM_SCHEDULER_DAILY_POLL, EM_CONTROLLER WHERE EM_SCHEDULER_DAILY_POLL.CONTROLLER_ID =
EM_CONTROLLER.CONTROLLER_ID AND EM_SCHEDULER_DAILY_POLL.DATE_TIME
BETWEEN '26-Jun-2019' AND '26-Jun-2019 23:59:59' AND
POLLED_SUCCESSFULLY=0 AND EM_SCHEDULER_DAILY_POLL.CONTROLLER_ID=30
[22007-199]
This SQL works perfectly on SQL server but gives above exception on H2DB. How to solve this issue? I need both date and time in query.
Try using ISO date literals:
WHERE
EM_SCHEDULER_DAILY_POLL.DATE_TIME >= '2019-06-26' AND
EM_SCHEDULER_DAILY_POLL.DATE_TIME < '2019-06-27'
Note that since you are just looking for records on a single date, you could also try casting the column to date and doing a single comparison:
WHERE CAST(EM_SCHEDULER_DAILY_POLL.DATE_TIME AS DATE) = '2019-06-26'
As another comment, the first version I gave, with the two inequalities is sargable, meaning that the database should be able to use an index on the DATE_TIME column, while the second version, using the cast to date, probably cannot use an index. Therefore, the first version is the preferred way to go, if you ever need to tune or optimize your database.
You are passing a value with a time but H2 Date only don't have one.
Just remove the time in your second constant.
'26-Jun-2019 23:59:59' --> '26-Jun-2019'
DATE The date data type. The format is yyyy-MM-dd.
Mapped to java.sql.Date, with the time set to 00:00:00 (or to the next
possible time if midnight doesn't exist for the given date and
timezone due to a daylight saving change). java.time.LocalDate is also
supported on Java 8 and later versions.
Example:
DATE
Source :Data type of H2.
And since you just want one day (at least in that example), you can simply use :
DATE_TIME = '26-Jun-2019'
Note that Tim Biegeleisen's answer about ISO should be checked too, this format is not the best
Use TO_DATE function
Example - TO_DATE('01-12-2019','dd-MM-yyyy')
Insert into student(Id,Name,DOB) values(1, 'Abc', TO_DATE('01-12-2019','dd-MM-yyyy'))
There is a converter PARSEDATETIME() fuction.
For example if the date is 12/03/2013 we need to convert as PARSEDATETIME('12/03/2013','dd/MM/yyyy') check this SO.
The SQL statement look like Insert into invoice(id, invoice_date) values(1, PARSEDATETIME('12/03/2013','dd/MM/yyyy'))

assigning value from sql request of type datetime into java.util.Date variable [duplicate]

So far, I have not found a clear answer to this.
I'd like to know what the equivalent is for a SQL type DATETIME and the java type, using a PreparedStatement.
I have found: http://www.java2s.com/Code/Java/Database-SQL-JDBC/StandardSQLDataTypeswithTheirJavaEquivalents.htm
But it states that SQL type "DATETIME" is the same as sql.date, but when looking at the SQL date docs (http://download.oracle.com/javase/7/docs/api/java/sql/Date.html), it says the time is truncated (all zeros).
What I want is to be able to specify a preparedStatement.setDateTime() or some sort.
The only other way I see is using a timestamp, but that would require me to change the column type, while I cannot imagine someone else never had this problem before?
Any hints?
Edit: I am using MYSQL.
The java.sql package has three date/time types:
java.sql.Date - A date only (no time part)
java.sql.Time - A time only (no date part)
java.sql.Timestamp - Both date and time
You want the last one: java.sql.Timestamp.
If you are using these types, you don't need to call a specific setter; just use:
java.util.Date date = new Date();
Object param = new java.sql.Timestamp(date.getTime());
// The JDBC driver knows what to do with a java.sql type:
preparedStatement.setObject(param);
The equivalent of MS SQL Server or MySQL DATETIME data type or Oracle DATE data type is java.sql.Timestamp.
In Java we have java.util.Date to handle both Date and Time values.
In SQL, you have commonly Dates (only dates), Time (only time) and DateTime/Timestamp (date and time).
In your Java program, usually you'll always have java.util.Date, so each time you're setting Dates/Times/DateTimes in PreparedStatements, always choose exactly which one you need, according to the database.
I had a similar problem with my Mysql having SQL date and locally in my app i only had Date
I solved like this
java.sql.Date dataStartSql = new java.sql.Date(start.getTime());
After that used the setDate normally, and I used a getTimestamp to retrive the first value.
where start is a Date object.

Hibernate java.sql.Date field return only date for Oracle

I am using oracle database for retrieving date and time but it is returning only date when I am using java.sql.Date . I have tried with java.sql.Timestamp but its gave exception as wrong column type. I tried with V8Compatible configuration. But it is also not working. I cannot change anything in the DB side. In DB that column is of type DATE.
Please Give a suggestion
Some code would be nice, but did you try to annotate your date field with #Temporal(TemporalType.TIMESTAMP)?
For this, you should use ojdbc14.jar and oracle.sql.DATE
Source
You can try for inserting timestamp with precision of 2. Check this Stack Overflow Question.
As Oracle Date datatype is equivalent to java.sql.Timestamp in Java. Reference
Or simply go for java.util.Date, It should work.
An easy way to format and insert. Something like this example
Prior to 9.2, the Oracle JDBC drivers mapped the DATE SQL type to java.sql.Timestamp. This made a certain amount of sense because the Oracle DATE SQL type contains both date and time information as does java.sql.Timestamp. The more obvious mapping to java.sql.Date was somewhat problematic as java.sql.Date does not include time information. It was also the case that the RDBMS did not support the TIMESTAMP SQL type, so there was no problem with mapping DATE to Timestamp.
In 9.2 TIMESTAMP support was added to the RDBMS. The difference between DATE and TIMESTAMP is that TIMESTAMP includes nanoseconds and DATE does not. So, beginning in 9.2, DATE is mapped to Date and TIMESTAMP is mapped to Timestamp. Unfortunately if you were relying on DATE values to contain time information, there is a problem.
There are several ways to address this problem in the 9.2 through 10.2 drivers:
Alter your tables to use TIMESTAMP instead of DATE. This is probably rarely possible, but it is the best solution when it is.
For more information
Refer: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
make sure go with below code once, as first one is for timestamp creation and then go with get method for retrieving the date android time from oracle database.
......................
java.util.Date android = new java.util.Date();
long t = android.getTime();
java.sql.Date sqlDate = new java.sql.Date(t);
java.sql.Time sqlTime = new java.sql.Time(t);
java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(t);
......................
pstmt.getDate(2, sqlDate);
pstmt.getTime(3, sqlTime);
pstmt.getTimestamp(4, sqlTimestamp);
pstmt.executeUpdate();

Hibernate date conversion

I have a wierd hibernate related issue while setting a date field in an entity.
The date is interpreted as UTC in the java program (i did a System.out to make sure the date assigned is in 'UTC'. However, when hibernate actually persists to the database, the date is converted to local time and stored)
ex. the value has been set in the entity setter as "2009-09-09 00:08:08" - GMT
the actual value persisted to the database is "2009-09-08 08:08:08" - eastern time US.
I am unable to find out where and why this is happening and how to prevent it. Thanks
P.S. I am using joda date library and annotate the field with
#org.hibernate.annotations.Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
However, when hibernate actually persists to the database, the date is converted to local time and stored) ex. the value has been set in the entity setter as "2009-09-09 00:08:08" - GMT the actual value persisted to the database is "2009-09-08 08:08:08" - eastern time US.
Ok, first, whatever column type are you using to store your date in MySQL (TIMESTAMP or DATETIME), neither stores the time zone. From Re: Storing timezone with datetime:
TIMESTAMP is seconds since 1970, sitting in 4 bytes. It is stored in GMT. That is, the TZ offset is applied as you store a value, then reapplied when you fetch it. (...)
DATETIME is an 8-byte string of digits "yyyymmddhhmmss". (...)
And second, unless a buggy behavior, my understanding is that the conversion is supposed be done either by the server or by the JDBC driver depending on the the server time zone settings so that you don't get inconsistent data.
In both cases, my point is that storing "2009-09-09 00:08:08" - GMT or "2009-09-08 08:08:08" - eastern time US from Java should yield to the same value in the database.
However, it looks like a different conversion is done when displaying them. This begs the question: how did you actually check the value of the "persisted date". Does the "problem" occur in your SQL client? In Java code?
References
9.6. MySQL Server Time Zone Support
21.3.4.1. Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J
Bug #15604: TimeZone discarded storing java.util.Calendar into DATETIME
MySQL documentation for DateTime says "MySQL retrieves and displays DATETIME values in 'YYYY-MM-DD HH:MM:SS' format". That means mysql converts the 'milliseconds since epoch' to the above format. So now my question becomes, is timezone info also stored in mysql?
I've updated my initial answer (which was not totally accurate/exhaustive). Whether you're using DATETIME or TIMESTAMP, the answer is no.
Another observation I made is, the above date 'conversion' issue exists only when Im setting the date in the Java application. If I create a mysql trigger to update/set date using 'UTC_TIMESTAMP()', the date is displayed in the 'UTC' time.
The UTC_TIMESTAMP() function always returns the current UTC date and time.
What I'd like to know is:
How did you "reveal" the problem? With a SQL client or from Java?
What is the local time zone of the JVM?
What is the MySQL Server time zone?
What is the version of the MySQL JDBC Driver?
Could you do a test with raw JDBC?
In order to treat dates as UTC in the DB (for read/write), you can use this small open source library DbAssist. It uses a custom UtcDateType in order to map java.util.Date fields in your entities, so that they are treated by Hibernate as UTC in the DB. Since you are using JPA annotations, you would use the following dependency:
<dependency>
<groupId>com.montrosesoftware</groupId>
<artifactId>DbAssist-5.2.2</artifactId>
<version>1.0-RELEASE</version>
</dependency>
Applying the fix is easy, for example, when using Spring Boot, you have to make sure that you have #EnableAutoConfiguration annotation before the application class. If you are using another Hibernate version, just refer to github wiki to find the proper version of the fix and the installation guide. You can also read more about the time zone shift issue in this article.
This behaviour of Joda Time Contrib is fixed in my project Usertype for Joda Time and JSR310. See http://usertype.sourceforge.net/ which is practically otherwise a drop in replacement for JodaTime Hibernate.
I have written about this issue: http://blog.jadira.co.uk/blog/2010/5/1/javasqldate-types-and-the-offsetting-problem.html
Hope this helps,
Chris

Categories