java.util.Date
¿vs java.sql.Date
: Cuándo usar el cual y por qué?
Respuestas
¿Demasiados anuncios?Felicidades, has llegado a mi mascota favorita pone de mal humor con JDBC: Fecha de la clase de manejo.
Básicamente las bases de datos suelen apoyar al menos tres formas de campos de fecha y hora que se la fecha, la hora y la fecha y hora. Cada uno de estos tienen una clase correspondiente en JDBC y cada uno de ellos se extienden java.util.Date
. Rápido semántica de cada una de estas tres son las siguientes:
-
java.sql.Date
corresponde a SQL FECHA que significa que las tiendas de años, meses y días , mientras que de la hora, minuto, segundo y milisegundo son ignorados. Además,sql.Date
no está ligado a las zonas horarias. -
java.sql.Time
corresponde a SQL TIEMPO y como debería ser obvio, sólo contiene información sobre la hora, minutos, segundos y milisegundos. -
java.sql.Timestamp
corresponde a SQL marca de tiempo que es la fecha exacta para el nanosegundo (tenga en cuenta queutil.Date
sólo admite milisegundos!) personalizable de precisión.
Uno de los más comunes errores en los controladores JDBC en relación a estos tres tipos es que los tipos se manejan de forma incorrecta. Esto significa que sql.Date
está en la zona horaria específica, sql.Time
contiene corriente año, mes y día, et cetera, et cetera.
Por último: ¿cuál usar?
Depende del tipo SQL de el campo, la verdad. PreparedStatement
ha incubadoras para los tres valores, #setDate()
siendo el uno para sql.Date
, #setTime()
para sql.Time
y #setTimestamp()
para sql.Timestamp
.
Tenga en cuenta que si utilizas ps.setObject(fieldIndex, utilDateObject);
puede dar realmente una normal util.Date
para la mayoría de los controladores JDBC que estará feliz de devorar como si fuera del tipo correcto, pero cuando usted solicita los datos después de esto, usted puede notar que en realidad estás faltan cosas.
Realmente estoy diciendo que ninguna de las Fechas debe ser utilizado en su totalidad.
Lo que yo estoy diciendo que guardar el milisegundos/nanosegundos en formato anhela y convertirlos en objetos de cualquier cosa que se esté utilizando (obligatorio joda tiempo de enchufe). Un hacky manera que se puede hacer es almacenar el componente de fecha como una larga y componente de tiempo como de otra, por ejemplo ahora mismo sería 20100221 y 154536123. Estos números de magia puede ser utilizado en consultas de SQL y serán portátiles de la base de datos a otra y te permitirá evitar esta parte de JDBC/Java Fecha de la API:s completamente.
java.sql.Date
- al llamar a los métodos/constructores de las bibliotecas que lo utilizan (como JDBC). No de otro modo. No quiero presentar a las dependencias en la base de datos de las bibliotecas de aplicaciones/módulos que explícitamente no lidiar con JDBC.
java.util.Date
- cuando el uso de las bibliotecas que usan. De lo contrario, como poco como sea posible, por varias razones:
Es mutable, lo que significa que usted tiene que hacer una defensa copia de la misma cada vez de pasar o de retorno de un método.
No manejar fechas muy bien, que al revés de la gente como el tuyo realmente, creo que la fecha de manejo de clase.
Ahora, porque j.u.D no hacer su trabajo muy bien, la horrorosa
Calendar
clases fueron introducidas. También son mutables, y terrible para trabajar, y deben ser evitados si usted no tiene ninguna opción.Hay alternativas mejores, como la Joda de la API de Tiempo (
que puede incluso hacer en Java 7 y convertirse en la nueva fecha oficial de manejo de API- una búsqueda rápida le dice que no).
Si usted siente que es una exageración para introducir una nueva dependencia como Joda, long
s no son nada malos para uso de campos de fecha en objetos, aunque yo generalmente se envuelven en j.u.D cuando se les pasa de todo, para el tipo de seguridad y documentación.
El java.util.Date clase en Java que representa un momento concreto en el tiempo (e .g., 2013 Noviembre 25 16:30:45 hacia abajo para milisegundos), pero el tipo de datos de FECHA en el DB representa una fecha (e.g., 2013 Noviembre 25). Para evitar que proporciona un java.util.Date objeto a la base de datos por error, Java no permite establecer un parámetro SQL para java.util.Date directamente:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work
Pero todavía permite que hacerlo por la fuerza/de la intención (luego de horas y minutos serán ignoradas por la base de datos del controlador). Esto se hace con el java.sql.Date clase:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work
Un java.sql.Date objeto puede almacenar un momento en el tiempo (de modo que es fácil construir a partir de un java.util.Date), pero producirá una excepción si se intenta preguntar por el horario (para imponer su concepto de ser una fecha única). La base de datos del controlador se espera que reconocer esta clase y sólo use 0 para las horas. Intente esto:
public static void main(String[] args) {
java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
java.sql.Date d2 = new java.sql.Date(12345);
System.out.println(d1.getHours());
System.out.println(d2.getHours());
}