BLToolKit: how to fetch 'empty' datetime field? - mysql

Request Execute is failed if one of fields to be mapped has DateTime field and corresponding value in DB has '0000-00-00' or '0001-01-01'. The following error is returned
Unable to convert MySQL date/time value to System.DateTime
Is there any possibility to fetch such value?
I've tried to specify the 'DateTime?' value as property type - it doesn't help too (actually, I didn't expect that to be helpful).
P.S. I use MySql 5.1

I came across a similar problem using NHibernate with the same error in an exception.
It's due to MySQL's unique "feature" of allowing invalid dates in a DATE field, especially using 0000-00-00 as a default value for DATE NOT NULL columns. When such a date is encountered, it throws an exception when converting itself to a DateTime.
The suggested solution for this was to add
Allow Zero Datetime=True;
to the connection string, however in practice this did not work for me. I eventually solved the problem by altering the connection string adding
Convert Zero DateTime=true;
so your app.config section would look something like this
<connectionStrings>
<add
name="ConnectionString.MySql"
connectionString="Server=localhost;Port=3306;Database=BLT;Uid=someuser;Convert Zero DateTime=true;"
providerName="MySql.Data.MySqlClient"/>

Have you tried the MapValue attribute? I'm not sure if this will work but...
[MapValue(null, "0000-00-00")]
[MapValue(null, "0001-01-01")]
public DateTime? theDate;

i think you have to control it by another property.
[MapField("the_date")]
public DateTime? theDate; // Map
[MapIgnore]
public DateTime theDateControl
{
set {
if(theDate.HasValue)
{
....
}
}
}

Related

Google Apps Script - MySQL data import using JDCB does not work with Date 0000-00-00 [duplicate]

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

MYSQL OrmLiteWriteCommandExtensions

I'm getting an error from OrmLiteWriteCommandExtensions in my log, and I can't seem to find where this happens. I have no loss of data; when I have the logfactiory set to null, it breaks on no errors; I have set it to allow zero date, but that didn't help. I not sure how to debug this or get around it. It clogs up my logg with statements that I can't track.
This occurs on both linux and windows.
Doesn anyone have an idea how to get at this?
OrmLiteWriteCommandExtensions System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style)
at System.DateTime.ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style)
at ServiceStack.Text.Common.DateTimeSerializer.ParseShortestXsdDateTime(String dateTimeStr)
at ServiceStack.OrmLite.Converters.DateTimeConverter.FromDbValue(Type fieldType, Object value)
at ServiceStack.OrmLite.OrmLiteWriteCommandExtensions.PopulateWithSqlReader[T](T objWithProperties, IOrmLiteDialectProvider dialectProvider, IDataReader reader, Tuple`3[] indexCache, Object[] values)
UPDATE:
The logging occurs in the correct file set in the nlog config file, BUT for this exception only it does not conform to formatting in the layout set for NLOG (all other exceptions do!).
Layout string:
${longdate} ${machinename} ${logger} ${level} ${message} ${onexception:EXCEPTION OCCURRED:${exception:format=type,message,method:maxInnerExceptionLevel=5:innerFormat=shortType,message,method}}
UPDATE2 SOLVED:
So this was fun... Before I start to explain how I solved it I have to say that I have no idea why it writes in the correct log file, but ignore all formatting for logging errors - that be another dragon to slay for another time.
So the problem was that a varchar field in the mysql database had birthdate as string and the implicit conversion between DateTime in dotnet to string thre an error.
After changing the field to datetime in thet database the error went away.
Funny thing is that I hade to set minlevel to trace to get the error in context with its call to the database - but it still ignored all error formatting, had no stacktrace, no sql statement, and no line number associated with the error in the log.
So the problem was that a varchar field in the mysql database had birthdate as string and the implicit conversion between DateTime in dotnet to string thre an error.
After changing the field to datetime in thet database the error went away.
Funny thing is that I had to set minlevel to trace to get the error in context with its call to the database - but it still ignored all error formatting, had no stacktrace, no sql statement, and no line number associated with the error in the log.

Storing milliseconds in MySQL timestamp column using Hibernate

I'm trying to store a java Date with milliseconds in MySQL's timestamp column using Hibernate, but the millisecods are stored always as .000.
The definition of the column in hibernate is as follows:
#Type(type="timestamp")``
private Timestamp timestamp;
In DB the column is declared as TIMESTAMP(3)
I've tried different combinations, including Date, but neither helped.
I use MySQL 5.6.25, Connector/J version 5.1.37, Hibernate 4.0.1.
I've been investigating it for a while, but still couldn't find any solution that works form me.
ANy help will be appreciated.
Have you tried using DATETIME(3) or TIMESTAMP(4)? I believe both of these will give you the milliseconds. If you are trying to get the millisecond time where the interatction happens such as the row becomes updated you can use ON UPDATE DATETIME(3)
It seems that Hibernate and MySql interaction removes de milliseconds precision of your Date/Timestamp Java property. I have the same problem.
My solution is to "hack" hibernate telling that the entity property is an string and then serializing/deserializing the value in the setter/getter
#Column(name="time")
private String time
...
public Date getTime(){
return strTodate( this.time );
}
public void setTime(Date value){
this.time = dateToStr( value );
}
When MySQL receives an String for a Datetime(3) column, string is properly converted and milliseconds are not lost :-)
Fortunately, when reading from MySQL, Datetime(3) is propery serialized to string without milliseconds lost
The string date format used is "yyyy-MM-dd hh:mm:ss.SSS"
The idea of this solution is, don't let hibernate deal with dates. Delegate the responsability to MySql.
Unfortunatelly, MySQL doesn't accept an standard ISO string (i.e.: "yyyy-MM-ddThh:mm:ss.SSSZ") and this solution is not compatible with postgres (string date format is not the same)

Timestamp field can only by updated via behavior in Yii

In my model, I have a field named timestamp (MySQL type: timestamp) defined in safe validator and I'm unable to write it manually. Each time I call:
$model->timestmap = time();
$model->save();
model is saved (row created / updated), that is -- it passes validation without errors, but timestamp field is filled with default value of 0000-00-00 00:00:00 (I decided to remove default on update CURRENT_TIMESTAMP attribute, I don't want MySQL to handle this).
However, when I remove above code and attach CTimestampBehavior instead, field is being filled with correct values on both update and create, without any problems.
What can be happening or what am I missing? How can behavior update field without problems, while my manual attempt fails? Is this because column type is timestamp, not datetime or int?
I was always told, that first clue, why some attribute isn't saved, is because it is not listed among safe validator list or because it is listed on unsafe validator list. But this one is listed on safe list.
Your database field is a datetime field (i assume, looking at your default value), but your filling it with a unix timestamp. Try it with an CDbExpression instead:
$model->timestamp = new CDbExpression('NOW()');
$model->save();
I usually use $model->timestamp = date('Y-m-d H:i:s'), it works perfectly
As the other answers already suggested:
The timestamp needs to be converted into a MySQL compatible date format string somehow upon saving and the other way around when loading. Now you already discovered that the CTimestampBehavior does this for you but unfortunately it doesn't care about loading.
IMO the best solution for you is something along the way of:
public function beforeSave()
{
$this->timestamp = date('Y-m-d H:i:s', $this->timestamp);
return parent::beforeSave();
}
public function afterSave()
{
// Turn it back into a unix timestamp in case you want to continue working with the record
$this->timestamp = CDateTimeParser::parse($this->timestamp, 'yyyy-MM-dd hh:mm:ss');
parent::afterSave();
}
public function afterFind()
{
$this->timestamp = CDateTimeParser::parse($this->timestamp, 'yyyy-MM-dd hh:mm:ss');
return parent::afterFind();
}
It's a lot of work for a stupid timestamp and so for myself I have an auto type conversion behaviour that I link to my models. This behaviour uses the table metadata to take care of everything automatically. Might be a good idea to invest in that. I've thought about making mine open source but it's a bit of a mess atm ;)
But the code above will give you unix times to work with during executing and whilst saving it will temporary convert into a mysql datetime string
Hope that helps.

Entity Framework - MySQL - Datetime format issue

I have a simple table with few date fields.
Whenever I run following query:
var docs = ( from d in base.EntityDataContext.document_reviews
select d ).ToList();
I get following exception:
Unable to convert MySQL date/time value to System.DateTime.
MySql.Data.Types.MySqlConversionException: Unable to convert MySQL date/time value to System.DateTime
The document reviews table has two date/time fields. One of them is nullable.
I have tried placing following in connection string:
Allow Zero Datetime=true;
But I am still getting exception.
Anyone with a solution?
#effkay - if you solved this it would be great if you could post the answer.
Also if anyone else has a solution that would be great too :).
Edit:
The solution can be found in the http://dev.mysql.com/doc/refman/5.1/en/connector-net-connection-options.html connector documentation.
I needed to set "Convert Zero Datetime" to true, and now it works.
hth.
You need to set Convert Zero Datetime=True in connection string of running application