I'm generating one date and saving in a database through hibernate, and when I get the value and I compare with the value before it was inserted. The result is not equal!
I created the date as following
Date rightnow = Calendar.getInstance().getTime();
Task t1 = new Task("My task", rightnow);
taskDao.saveOrUpdate(t1);
Task taskR1 = taskDao.get(t1.getIdTask());
assertEquals("They should have to be equal dates",taskR1.getDate(),t1.getDate());
I'm getting this error
<2014-04-11 23:13:13.0>
is different to <Fri Apr 11 23:13:13 CEST 2014>
java.lang.AssertionError:
They should have to be equal dates
expected:<2014-04-11 23:13:13.0>
but was:<Fri Apr 11 23:13:13 CEST 2014>
Extra info related with the problem
Class Task
@Entity
@Table(name = "t_task")
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "idTask")
private long idTask;
...
@Column(name = "date")
private Date date;
...
Mysql table t_task
CREATE TABLE IF NOT EXISTS `mytask`.`t_task` (
`idTask` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`date` DATETIME NOT NULL
...
I created a new hashCode() and equals() functions in Task, with only date field and even so it is different.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Task))
return false;
Task other = (Task) obj;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
return true;
}
Any idea?
Sun's explanation, working with java client level (not with Hibernate), in the javadoc for java.sql.Timestamp, it states:
Quote: public class Timestamp extends Date
A thin wrapper around java.util.Date that allows the JDBC API to identify this as an SQL TIMESTAMP value. It adds the ability to hold the SQL TIMESTAMP nanos value and provides formatting and parsing operations to support the JDBC escape syntax for timestamp values.
Note: This type is a composite of a java.util.Date and a separate nanoseconds value. Only integral seconds are stored in the java.util.Date component. The fractional seconds - the nanos - are separate. The Timestamp.equals(Object) method never returns true when passed a value of type java.util.Date because the nanos component of a date is unknown. As a result, the Timestamp.equals(Object) method is not symmetric with respect to the java.util.Date.equals(Object) method. Also, the hashcode method uses the underlying java.util.Date implementation and therefore does not include nanos in its computation.
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
@Test
public void testTimestampVsDate() {
java.util.Date date = new java.util.Date();
java.util.Date stamp = new java.sql.Timestamp(date.getTime());
assertTrue("date.equals(stamp)", date.equals(stamp)); //TRUE
assertTrue("stamp.compareTo(date)", stamp.compareTo(date) == 0); //TRUE
assertTrue("date.compareTo(stamp)", date.compareTo(stamp) == 0); //FALSE
assertTrue("stamp.equals(date)", stamp.equals(date)); //FALSE
}
From javadoc we can figure out that:
Timestamp = java.util.Date + nanoseconds
and
The Timestamp.equals(Object) method never returns true when passed a value of type java.util.Date because the nanos component of a date is unknown.
Timestamp compareTo() function
public int compareTo(java.util.Date o) {
if(o instanceof Timestamp) {
// When Timestamp instance compare it with a Timestamp
// Hence it is basically calling this.compareTo((Timestamp))o);
// Note typecasting is safe because o is instance of Timestamp
return compareTo((Timestamp)o);
} else {
// When Date doing a o.compareTo(this)
// will give wrong results.
Timestamp ts = new Timestamp(o.getTime());
return this.compareTo(ts);
}
}