java - parse - Comparando las fechas mapeadas de hibernación?
localdate hibernate (4)
¿Cómo puedo asignar una fecha de un objeto java a una base de datos con Hibernate? Intento diferentes enfoques, pero no estoy contento con ellos. ¿Por qué? Déjame explicar mi problema. Tengo la siguiente clase [1] que incluye el método principal que invoco y con la siguiente asignación [2]. El tema sobre este enfoque se puede ver cuando se mira la salida de la consola.
falso
falso
1
-1
1224754335648
1224754335000
Jue 23 de octubre 11:32:15 CEST 2008
Reloj @ 67064
Como puede ver, las fechas no son exactamente iguales, aunque deberían serlo, por lo que es difícil compararlas sin perder el tiempo con el valor de retorno de getTime
. También probé java.sql.Date, Timestamp y date en lugar de timestamp en el mapeo, pero sin éxito.
Me pregunto por qué los últimos tres dígitos son cero y si esto es un problema de hibernación o java o mi propia estupidez.
Gracias por leer.
[1]
public class Clock {
int id;
java.util.Date date;
public static void main(String[] args) {
HibernateUtil.init();
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
Clock clock = new Clock();
clock.date = new java.util.Date();
HibernateUtil.getSessionFactory().getCurrentSession().saveOrUpdate(clock);
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
Clock fromDBClock = (Clock)HibernateUtil.getSessionFactory()
.getCurrentSession().get(Clock.class, 1);
System.out.println(clock.date.equals(fromDBClock.date));
System.out.println(fromDBClock.date.equals(clock.date));
System.out.println(clock.date.compareTo(fromDBClock.date));
System.out.println(fromDBClock.date.compareTo(clock.date));
System.out.println(clock.date.getTime());
System.out.println(fromDBClock.date.getTime());
System.out.println(clock.date.toString());
System.out.println(fromDBClock.toString());
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
HibernateUtil.end();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
}
[2]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Clock" table="CLOCK">
<id name="id" column="CLOCK_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp"/>
</class>
</hibernate-mapping>
Aparentemente, el tipo TIMESTAMP en su RDBMS objetivo ( ¿qué está usando, por cierto? ) No almacena milisegundos. Intenta encontrar otro tipo nativo que sí lo haga, o asigna tu tiempo a otra cosa, como long = ms-from-epoch.
La precisión de MySql DateTime es solo la segunda. La precisión de la fecha Java es en milisegundos. Es por eso que los últimos tres dígitos son ceros después de haber sido puestos en la base de datos.
Haz esto con tu Fecha original:
date = date.setTime ((date.getTime () / 1000) * 1000);
Esto lo establecerá en el último segundo exacto, y todas sus comparaciones coincidirán.
(BTW, System.out.println (fromDBClock.toString ()); debe ser System.out.println (fromDBClock.date.toString ());
Personalmente, trunco cada fecha que recibo en mi objeto POJO con la clase del paquete lang commons Apache llamado DateUtils.
Ver [sitio de Apache commons] [1]
[1]: http://commons.apache.org/lang/api/org/apache/commons/lang/time/DateUtils.html#truncate(java.util.Date , int)
SQL Server almacena datetime con una precisión de 3 milisegundos que definitivamente puede causar el problema que está viendo. Una consecuencia de esto es que 23: 59: 59.999 en Java termina siendo el día siguiente en SQL Server. Nunca he tenido un problema con Oracle, Informix o MySQL, pero otras bases de datos también pueden tener menos precisión. Puede solucionarlo utilizando tipos personalizados de Hibernate. Tiene que redondear a algo menos preciso que la precisión de la base de datos subyacente cuando escribe los valores de fecha. Busque UserType en la documentación de Hibernate, va a cambiar el método nullSafeSet para redondear.