the issue that i have at the moment is i cannot retrieve a date object from my mysql database, so far no matter what i try, i either get
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
or
java.sql.SQLException: Value '0000-00-00' can not be represented as java.sql.Date
does anyone have an idea regarding what can be done to solve this.
i have tried this and this but i still come to the same two errors which are both caused by the date
In addition to what the others have answered (including the very good advice that storing invalid dates is not a good idea) you can also instruct the JDBC driver to handle those invalid dates differently:
From: http://dev.mysql.com/doc/refman/5.5/en/connector-j-installing-upgrading.html
Connector/J 3.1 throws an exception by default when these values are encountered as this is the most correct behavior according to the JDBC and SQL standards. This behavior can be modified using the zeroDateTimeBehavior configuration property. The permissible values are:
- exception (the default), which throws an SQLException with an SQLState of S1009.
- convertToNull, which returns NULL instead of the date.
- round, which rounds the date to the nearest closest value which is 0001-01-01.
I would recommend to use convertToNull
See here for a description on how to specify configuration properties.
'0000-00-00' is an invalid date. It should not exist in your data.
Therefore, you need to either:
clean up the data and turn off allow_invalid_dates in your MySQL configuration (see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_allow_invalid_dates)
write java code to catch the date exceptions and deal with the bad data
write SQL to substitute a default date for invalid date, as suggested by John Woo.
The problem with 3 is that there are other invalid dates (e.g. '2012-02-31') that might throw exceptions also. Good luck.
if you are retrieving rows from the database, format the dates in your select statement,
SELECT if(colDate = '0000-00-00', curdate(), colDate), ....
just replace CURDATE() to your desired default date. The reason why the exception arises is because 0000-00-00 is not a valid date.
Related
I am filtering a search with criteria object.
but the filter doesn't work for date.
I made this for instance :
criteria.add(Restrictions.and(
Restrictions.like("serialNumber", device.getSerialNumber()),
Restrictions.like("installDate", device.getInstallDate()), // a date
Restrictions.like("ipAdress", device.getIpAdress())));
then i made this :
else if (device.getInstallDate() != null) {
criteria.add(Restrictions.like("installDate", device.getInstallDate()));
}
Do you have any idea to filter by date ?
Your code/approach looks fine. You may want to enable SQL logging to see what statements exactly are sent to the DB and what values are bound to the statement parameters. This should help you figure out the issue (the issue may be just some detail like e.g. dates with/without time parts, or something similar).
See also:
Hibernate show real SQL
To search for exact dates I use:
criteria.add(Restrictions.eq("installDate", device.getInstallDate()));
Note also that dates and timestamps are treated differently by the underlying database based on the corresponding SQL types. A field declared as a date will not include hours/minutes/etc. If the desire is to compare both date and time, be sure to use timestamp in the Hibernate declaration.
The fastest way to show the SQL statements is to set the show_sql property to true in your Hibernate configuration
I have hibernate mapping as follow:
<property formula="(Timediff(ifnull(sttime,now()),sstime))" insert="false" name="duration" update="false" />
where sstime is of type Timestamp
here this formula returns some value in this format "838:59:59" from my data.
I got the exception when i am trying to load this value in 'Duration' field, which has 'java.sql.Time' type, it gives me this exception.
"Generic JDBC exception - Bad format for Time '838:59:59'"
That's indeed not a valid time. You should not use a java.sql.Time to represent a duration, especially if this duration is potential longer tha 24 hours, since a Time represents the time portion of a date. Use a custom type instead, or simply a string that you'll parse yourself.
From the source
http://www.microshell.com/database/mysql/getting-around-mysql-timediff-maximum-value-of-8385959/
Use TIMESTAMPDIFF instead of TIMEDIFF in formulae
Following the MySQL documentation you should use TIMESTAMPDIFF() and UNIX_TIMESTAMP():
The result returned by TIMEDIFF() is limited to the range allowed for
TIME values. Alternatively, you can use either of the functions
TIMESTAMPDIFF() and UNIX_TIMESTAMP(), both of which return integers.
Query may look something like this, but is dependent from the result data type that you are using:
SELECT FROM_UNIXTIME(TIMESTAMPDIFF(SECOND,sstime,NOW())) FROM time_table;
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(sstime)) FROM time_table;
Demo
I'm getting this exception:
java.sql.SQLException: Value '0000-00-00' can not be represented as java.sql.Date
Originating from this code:
Date internalDate = rs.getDate(idx++);
Where rs is a ResultSet.
So this is fine to me - I know there are zero'ed dates in the database and I need to be able to read these and convert them into an appropriate (probably null) data in my downstream data structures. The problem is I don't know how to retrieve it and get a "soft" error. I thought about wrapping this line in a try/catch for SQLException but understand this will break validity of the ResultSet.
Is it possible to read this value in another way without throwing a SQLException?
I like #a_horse_with_no_name's answer, however if you don't have control over the connection, you could change the query to return a null instead:
select
...
case when my_date_col = '0000-00-00' then null else my_date_col end as my_date_col,
...
or the slightly more terse, but mysql-only, option:
if(my_date_col = '0000-00-00', null, my_date_col) as my_date_col
Also, caution is advised changing the entire application's JDBC behaviour as you may break code that relies on such dates being returned - perhaps they use rs.getString(i) instead. You would have to regression test all other queries to be sure.
You need to tell the JDBC driver to convert them to NULL. This is done by passing a connection property name zeroDateTimeBehavior with the value convertToNull
For more details see the manual: http://dev.mysql.com/doc/refman/4.1/en/connector-j-installing-upgrading.html
I suggest using rs.getString() and parsing the String yourself. If it is all 0s, then use a null Date reference. If not, create an appropriate Date object.
Set the column Allow Null, and Set Default Value at Column : 1900-01-01 was my best solution...
Convert this String result to a date by using "simpleDateFormat.parse(yourValue)"
Get day or year or month value from that date ( whichever you want)
This will return int value
Check if it is 0
If it is zero set date equal to null.
I have a database table containing dates
(`date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00').
I'm using MySQL. From the program sometimes data is passed without the date to the database. So, the date value is auto assigned to 0000-00-00 00:00:00
when the table data is called with the date column it gives error
...'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp.......
I tried to pass null value to the date when inserting data, but it gets assign to the current time.
Is there any way I can get the ResultSet without changing the table structure?
You can use this JDBC URL directly in your data source configuration:
jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull
Whether or not the "date" '0000-00-00" is a valid "date" is irrelevant to the question.
"Just change the database" is seldom a viable solution.
Facts:
MySQL allows a date with the value of zeros.
This "feature" enjoys widespread use with other languages.
So, if I "just change the database", thousands of lines of PHP code will break.
Java programmers need to accept the MySQL zero-date and they need to put a zero date back into the database, when other languages rely on this "feature".
A programmer connecting to MySQL needs to handle null and 0000-00-00 as well as valid dates. Changing 0000-00-00 to null is not a viable option, because then you can no longer determine if the date was expected to be 0000-00-00 for writing back to the database.
For 0000-00-00, I suggest checking the date value as a string, then changing it to ("y",1), or ("yyyy-MM-dd",0001-01-01), or into any invalid MySQL date (less than year 1000, iirc). MySQL has another "feature": low dates are automatically converted to 0000-00-00.
I realize my suggestion is a kludge. But so is MySQL's date handling.
And two kludges don't make it right. The fact of the matter is, many programmers will have to handle MySQL zero-dates forever.
Append the following statement to the JDBC-mysql protocol:
?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
for example:
jdbc:mysql://localhost/infra?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
Instead of using fake dates like 0000-00-00 00:00:00 or 0001-01-01 00:00:00 (the latter should be accepted as it is a valid date), change your database schema, to allow NULL values.
ALTER TABLE table_name MODIFY COLUMN date TIMESTAMP NULL
As an exteme turnaround, when you cannot do an alter to your date column or to update the values, or while these modifications take place, you can do a select using a case/when.
SELECT CASE ModificationDate WHEN '0000-00-00 00:00:00' THEN '1970-01-01 01:00:00' ELSE ModificationDate END AS ModificationDate FROM Project WHERE projectId=1;
you can try like This
ArrayList<String> dtlst = new ArrayList<String>();
String qry1 = "select dt_tracker from gs";
Statement prepst = conn.createStatement();
ResultSet rst = prepst.executeQuery(qry1);
while(rst.next())
{
String dt = "";
try
{
dt = rst.getDate("dt_tracker")+" "+rst.getTime("dt_tracker");
}
catch(Exception e)
{
dt = "0000-00-00 00:00:00";
}
dtlst.add(dt);
}
I wrestled with this problem and implemented the URL concatenation solution contributed by #Kushan in the accepted answer above. It worked in my local MySql instance. But when I deployed my Play/Scala app to Heroku it no longer would work. Heroku also concatenates several args to the DB URL that they provide users, and this solution, because of Heroku's use concatenation of "?" before their own set of args, will not work. However I found a different solution which seems to work equally well.
SET sql_mode = 'NO_ZERO_DATE';
I put this in my table descriptions and it solved the problem of
'0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
There was no year 0000 and there is no month 00 or day 00. I suggest you try
0001-01-01 00:00:00
While a year 0 has been defined in some standards, it is more likely to be confusing than useful IMHO.
just cast the field as char
Eg: cast(updatedate) as char as updatedate
I know this is going to be a late answer, however here is the most correct answer.
In MySQL database, change your timestamp default value into CURRENT_TIMESTAMP. If you have old records with the fake value, you will have to manually fix them.
You can remove the "not null" property from your column in mysql table if not necessary. when you remove "not null" property no need for "0000-00-00 00:00:00" conversion and problem is gone.
At least worked for me.
I believe this is help full for who are getting this below Exception on to pumping data through logstash
Error: logstash.inputs.jdbc - Exception when executing JDBC query {:exception=>#}
Answer:jdbc:mysql://localhost:3306/database_name?zeroDateTimeBehavior=convertToNull"
or if you are working with mysql
I'm using Hibernate 3.2.7.GA criteria queries to select rows from an Oracle Enterprise Edition 10.2.0.4.0 database, filtering by a timestamp field. The field in question is of type java.util.Date in Java, and DATE in Oracle.
It turns out that the field gets mapped to java.sql.Timestamp, and Oracle converts all rows to TIMESTAMP before comparing to the passed in value, bypassing the index and thereby ruining performance.
One solution would be to use Hibernate's sqlRestriction() along with Oracle's TO_DATE function. That would fix performance, but requires rewriting the application code (lots of queries).
So is there a more elegant solution? Since Hibernate already does type mapping, could it be configured to do the right thing?
Update: The problem occurs in a variety of configurations, but here's one specific example:
Oracle Enterprise Edition 10.2.0.4.0
Oracle JDBC Driver 11.1.0.7.0
Hibernate 3.2.7.GA
Hibernate's Oracle10gDialect
Java 1.6.0_16
This might sound drastic, but when faced with this problem we ended up converting all DATE columns to TIMESTAMP types in the database. There's no drawback to this that I can see, and if Hibernate is your primary application platform then you'll save yourself future aggravation.
Notes:
The column types may be changed with
a simple "ALTER tableName MODIFY
columnName TIMESTAMP(precisionVal)".
I was surprised to find that indexes
on these columns did NOT have to be
rebuilt.
Again, this only makes sense if you're committed to Hibernate.
According to Oracle JDBC FAQ:
"11.1 drivers by default convert SQL DATE to Timestamp when reading from the database"
So this is an expected behaviour.
To me this means that actual values coming from DATE columns are converted to java.sql.Timestamp, not that bind variables with java.util.Date are converted to java.sql.Timestamp.
An EXPLAIN PLAN output would help identifying the issue. Also, an Oracle trace could tell you exactly what type is assigned to the bind variable in the query.
If that's really happening it could be a Oracle bug.
You can work around it this way:
Create an FBI (Function Based Index) on the DATE column, casting it to a TIMESTAMP. For example:
CREATE INDEX tab_idx ON tab (CAST(date_col AS TIMESTAMP)) COMPUTE STATISTICS;
Create a View that contains the same CAST expression. You can keep the same column name if you want:
CREATE VIEW v AS
SELECT CAST(date_col AS TIMESTAMP) AS date_col, col_1, ... FROM tab;
Use the View instead of the Table (it's often a good idea anyway, e.g. if you were already using a View, you wouldn't need to change the code at all). When a java.sql.Timestamp variable will be used with date_col in the WHERE condition, (if enough selective) the Index will be used.
If you find out why there was a java.sql.Timestamp (or Oracle fixes the potential bug), you can always go back just changing the View (and dropping the FBI), and it would be completely transparent to the code