java - query - mongodb retrieve only one field
ResultSet#getDate() semántica (3)
ojdbc6-11.2.0.3.0
desde a ojdbc6-11.2.0.3.0
a ojdbc7-12.1.0.1
y observamos un cambio en la semántica ResultSet#getDate()
. Anteriormente el java.sql.Date
devuelto se ''normalizaría'' al establecer las horas, minutos, segundos y milisegundos en cero según el contrato especificado en java.sql.Date
. Con ojdbc7
este ya no es el caso y java.sql.Date
tiene las horas, los minutos, los segundos y los milisegundos configurados según el valor en la base de datos.
Miré el Javadoc de ResultSet#getDate()
y no dice explícitamente cuál de los comportamientos es el correcto. Yo hubiera asumido que el comportamiento anterior era lo que pretendía la especificación. ¿Estoy en lo cierto? ¿Hemos encontrado un error en el controlador?
Esto es claramente un error como la documentación de la clase java.sql.Date
estados
Para cumplir con la definición de SQL DATE, los valores de milisegundos envueltos por una instancia de java.sql.Date deben ''normalizarse'' al establecer las horas, minutos, segundos y milisegundos en cero en la zona horaria particular a la que está asociada la instancia. .
Analicé este problema en una base de datos 11g y puedo confirmar el comportamiento de PreparedStatement.setDate(index, java.sql.Date)
mencionado por el usuario de shonky linux ( ojdbc6-11.2.0.4-g
vs. ojdbc7-12.1.0.2
).
Si bien el nuevo comportamiento probablemente no viola explícitamente la especificación JDBC, ciertamente no encaja bien con el concepto de tener java.sql.Date
, java.sql.Time
y java.sql.Timestamp
y los tipos de datos correspondientes Types.DATE
, Types.TIME
y Types.TIMESTAMP
.
Por lo tanto, si bien en términos de "menos dolor para los clientes de Oracle existentes", la decisión según lo explicado por Douglas Surber podría tener sentido, no parece correcto desde una perspectiva de JDBC (independiente del DBMS).
Oracle no está cambiando la especificación JDBC. Hemos actualizado los documentos del controlador Oracle Database JDBC. Si hay algo en los documentos que sea confuso o incorrecto, lo solucionaremos. Sin embargo, no hay cambio en la especificación JDBC.
Las versiones anteriores de los controladores son inconsistentes. En algunos lugares, pusieron a cero los segundos. En otros lugares no lo hicieron. En 12.1 hicimos los controladores consistentes. La pregunta era, ¿cuál era el comportamiento correcto? De cualquier manera, algunos clientes verían un cambio en el comportamiento.
Después de un largo y vigoroso debate, decidimos que lo mejor para los clientes de Oracle Database no era poner a cero los segundos. Dejame explicar.
- El tipo ANSI SQL DATE no almacena segundos. La especificación JDBC asume en su mayoría ANSI SQL.
- El tipo DATE de la base de datos de Oracle almacena segundos. Los miembros del comité SQL de ANSI me han asegurado que esto es totalmente compatible con ANSI SQL.
- El objetivo de JDBC es exponer la base de datos. La especificación JDBC no define una base de datos abstracta con la intención de que los controladores implementen esa base de datos abstracta. Los controladores JDBC deben exponer los detalles de la base de datos, no ocultarlos. JDBC define herramientas para abstraer algunos detalles de la base de datos pero el programador tiene la opción de usar o no esas herramientas.
-
java.sql.Date
no impone el comportamiento de cero segundos, aunque podría hacerlo fácilmente. La responsabilidad recae en el programa para hacer cumplir o no aplicar ese comportamiento.
Entonces, Oracle DATE tiene segundos. El controlador JDBC de Oracle expone la base de datos Oracle. Si getDate
cero los segundos, perderá datos. Para algunos usuarios, esto no importaría, pero para otros sí lo sería. Dado que Oracle DATE almacena segundos, muchas bases de datos Oracle almacenan los tiempos con una segunda precisión en las columnas FECHA. Reducir a cero los segundos en esos casos perdería información.
Si el programa pasa una Fecha con segundos que no sean cero a setDate
, el programa ha creado una Fecha no conforme. Si el controlador pone a cero los segundos, el controlador desechó la información que el programa proporcionó y que la base de datos puede almacenar. De nuevo, el conductor ha perdido información.
Es bastante fácil escribir SQL o Java para poner a cero los segundos en get y set. Es más difícil evitar la pérdida de información, aunque ciertamente es posible.
Por lo tanto, decidimos hacer que los controladores mantuvieran constantemente los segundos en java.sql.Date
s. ResultSet.getDate
puede construir un java.sql.Date
con segundos distintos de cero, sin embargo, esto refleja con precisión lo que está en la base de datos. Como se señaló anteriormente, la implementación de Date podría haber aplicado esto pero no lo hizo. Una forma de verlo es que el programa creó la fecha en que lo almacenó en la base de datos, por lo que es responsabilidad del programa. El controlador solo está usando los datos que el programa proporcionó.
Lamento mucho que los conductores fueran inconsistentes antes. Nos esforzamos constantemente para limpiar las inconsistencias y casos de esquina extraños. Pero tenemos una enorme base instalada. Cada vez que cambiamos algo, incluso correcciones de errores obvias, algún cliente se ve afectado en alguna parte. Así que tratamos de encontrar un equilibrio entre mejorar los controladores y mantener la compatibilidad con versiones anteriores. 12c es un lanzamiento importante. Aprovechamos esa oportunidad para hacer algunos cambios más visibles. Lamentamos la interrupción, pero creemos que es lo correcto para los clientes en general.