2008-09-22 53 views
7

Estoy pasando por algunos objetos a través del servicio web y algunos de ellos contienen java.sql.Date. Debido a que Date no tiene un constructor vacío, no quiere ser serializado.Fecha de serialización en Java

La primera parte de una pregunta es fácil: ¿cuál es la mejor manera de pasar una fecha entre el cliente y el servicio?

Segunda parte es un poco complicado: una vez que decida cómo pasar fechas, obviamente puedo declarar la fecha transitoria y hacer una clase contenedora para pasar fechas como cadena o lo que sea, pero cómo aplicar la misma solución de la manera más transparente posible a varios clases que incluyen Fecha?

(tengo el presentimiento de que DynamicProxy cosita podría ser una solución, pero la lectura de documentación en el sitio de Sun no era muy útil, por lo que si realmente hay algo en esa dirección, una aclaración sería apreciada)

Editar : Formulé una pregunta incorrecta, lo siento (algún malentendido entre mí y compañero de trabajo, lo que en realidad es un problema). El problema ocurre debido a la deserialización. Entonces, una vez que tengo la fecha en formato xml, intenta deserializarse como GregorianCalendar. Otra parte de una pregunta permanece: ¿Cuál es la mejor manera de recibir algo (sello de tiempo largo o calendario Gregorian) y convertirlo a la fecha sql, sin hacer 10 envoltorios diferentes para 10 clases diferentes? Estoy usando un NetBeans para generación de código y wsdl.

Respuesta

2

java.sql.Date extiende java.util.Date

Sólo tiene que utilizar getTime() para obtener el valor a largo de ella. Esto se puede serializar y se puede construir un nuevo java.sql.Date (long) o un nuevo java.util.Date (long) en el otro extremo.

+0

Como entzik dijo anteriormente, esto pierde la zona horaria contenida en la Fecha. – Coderer

0

En primer lugar, si está utilizando servicios web, significa que está serializando a XML y no a su serialización habitual de Java (pero a otra biblioteca para calcular y desasignar). Entonces la pregunta carece de información.

En segundo lugar, si usted tiene control sobre su InputStream & OutputStream intentar extender ObjectOutputStream y ObjectInputStream y anular replaceObject() y resolveObject() y luego se puede implementar la serialización de java.sql.Date.

0

No necesita el constructor predeterminado (vacío) para serializar/deserializar la fecha (ya sea java.sql.Date o java.util.Date). Durante la deserialización no se llama al constructor, pero los atributos del objeto se establecen directamente en los valores de los datos serializados y puede usar el objeto tal como está, ya que se deserializó.

6

La serialización de la longitud devuelta por Date.getTime() como se sugirió anteriormente funcionará. Sin embargo, debe tener en cuenta que si su servidor está en otra zona horaria que el cliente, la fecha que reconstruirá en el otro lado será diferente. Si desea reconstruir el mismo objeto de fecha exacta, también debe enviar su zona horaria (TimeZone.getID()) y utilizarla para reconstruir la fecha en el otro lado.

+1

-1 - el valor largo es GMT, no requiere zonas horarias. –

+0

si serializa las 2pm en París obtendrá 8am si deserializa la misma transmisión en una máquina configurada para la zona horaria de NYC. Si desea programar una reunión, está bien porque quiere que todos asistan al mismo tiempo. Pero si necesita mostrar información contractual (por ejemplo: esta opción expira a las 2 p.m. en París), debe enviar a lo largo de la zona horaria para que la computadora de NY descubra que son las 2 p.m. y no las 8 a.m., y por cierto, en París. Existen casos empresariales para ambas situaciones, el envío a lo largo de la zona horaria siempre es seguro, excepto si tiene restricciones de ancho de banda estrictas. – entzik

0

Puede usar un codificador y decodificar para serializar y deserializar sus objetos.

Aquí es un ejemplo que serialises la clase SWT Rectángulo:

XMLEncoder encoder = new XMLEncoder(new FileOutputStream(file)); 
encoder.setPersistenceDelegate(
    Rectangle.class, 
    new DefaultPersistenceDelegate(new String[]{"x", "y", "width", "height"})); 
encoder.writeObject(groups); 
encoder.close(); 
1

He mirado en la implementación de java.sql.Date y como yo lo veo java.sql.Date es serializable como una extensión de java.util.Date.

8

Joda-Time

La clase Date cuenta con una API torpe. Una mejor implementación es Joda-Time.

ISO 8601

Joda-Time también le permite convertir su fecha en un formato estándar ISO 8601 (aaaa-mm-DDThh: MM: SS.sss). El uso de este estándar al mover las fechas del servidor a su cliente tiene la ventaja de incluir la fecha completa en un formato legible. Cuando utiliza, por ejemplo, JAXB, la representación XML de una fecha es también esta norma ISO. (Consulte la clase XMLGregorianCalendar)

+3

También tenga en cuenta que la próxima API JSR 310 Date & Time para Java 7 se basará en ISO8601 y conceptos de Joda Time. Entonces esta es una buena dirección para el futuro. –

+0

¡Gracias! No lo sabía yo mismo. Finalmente una mejor implementación de fecha. – JeroenWyseur

+0

Buen artículo sobre la nueva API: http://today.java.net/pub/a/today/2008/09/18/jsr-310-new-java-date-time-api.html – JeroenWyseur

3

Para responder a la primera parte de su pregunta, sugeriría una cadena en formato iso 8601 (este es un estándar para codificar fechas).

Para la segunda parte, no estoy seguro de por qué necesitarías una clase de proxy. O por qué tendrías que extender la clase de fecha para apoyar esto. p.ej. ¿su servicio web no sabría que un determinado campo es una fecha y realiza la conversión de fecha a cadena y viceversa? Necesitaría un poco más de información.

0

java.sql.Date ya implementa Serializable así que no hay necesidad de ponerlo en práctica :-)

En lo que se refiere a su pregunta principal, estoy profundamente enamorado de JAXB como puedo convertir casi cualquier XML en un objeto, por lo que puede valer la pena mirarlo.

0

Hmmm ... No se puede pensar en ningún motivo por el que una instancia de objeto serializada (serializada mediante el mecanismo java predeterminado) se deserialice como una instancia de otra clase ya que la información de clase debe ser una parte inherente de la serialización datos.

Por lo tanto, es un problema de su marco de (des) serialización o el marco acepta cualquier objeto "similar a una fecha" en el "extremo remitente" (Calendario, java.util.Date etc. - y así java.sql .Fecha también a medida que amplía java.util.Date), "lo serializa" en una cadena en algún formato de fecha común (por lo que se pierde la información del tipo) y lo "deserializa" de nuevo a un objeto de calendario en el extremo de recepción.

Así que creo que la forma más sencilla de llegar a java.sql.Date es hacer un

java.sql.Date date = new java.sql.Date(calendar.getTimeInMillis);

donde se necesita un java.sql.Date pero obtiene el GregorianCalendar detrás de la "desocialización".

1

una advertencia con java.sql.Fecha que recientemente me mordió es que no almacena las partes de tiempo (horas, minutos, segundos, etc.) solo la parte de la fecha. si quieres la marca de tiempo completa, tienes que usar java.util.Date o java.sql.Timestamp

1

Expandiré en el correct answer de JeroenWyseur.

ISO 8601

El formato estándar ISO 8601 es absolutamente la mejor manera de serializar un valor de fecha y hora para el intercambio de datos. El formato no es ambiguo, es intuitivo para las personas de todas las culturas y cada vez es más común en todo el mundo. Fácil de leer para humanos y máquinas.

2015-01-16T20:15:43+02:00 
2015-01-16T18:15:43Z 

El primer ejemplo tiene un desplazamiento de dos horas por delante de UTC. El segundo ejemplo muestra el uso común de Z ("Zulu") para indicar UTC, abreviatura de +00:00.

Joda-Time & java.time

Los java.util.Date & clases .calendar incluido con Java son notoriamente molesto, confuso, y defectuoso. Evítales. En lugar de utilizar ya sea:

  • Joda-Time biblioteca
  • paquete
  • java.time, incorporado en Java 8, inspirado por Joda-Time, definido por JSR 310.

Por defecto, las dos bibliotecas utilizan la norma ISO 8601 para analizar y generar representaciones de cadena de valores de fecha y hora.

Tenga en cuenta que java.time extiende el formato ISO 8601 al anexar proper name of the time zone, como 2007-12-03T10:15:30+01:00[Europe/Paris].

Busque StackOverflow.com para cientos de preguntas y respuestas con mucha discusión y código de ejemplo para ambas bibliotecas.

Evitar el conde-De-Época

Algunas de las otras respuestas recomiendan el uso de un número, un recuento de epoch. Este enfoque no es práctico. No es evidente por sí mismo. No es legible por el ser humano, lo que hace que la depuración sea problemática y frustrante.

¿Qué número es que, segundos enteros utilizados comúnmente en Unix, milisegundos utilizados en java.util.Date & Joda-Time, microsegundos utilizado comúnmente en bases de datos como PostgreSQL o nanosegundos utiliza en java.time package?

¿Cuál de las couple dozen epochs, primer momento de 1970 utilizado en Unix, año 1 utilizado en .Net & Go "0 de enero de 1900" que se utiliza en millones (mil millones?) De Excel & hojas de cálculo Lotus, o 1 de enero de 2001 utilizado por Cocoa?

diagram of different resolution of time tracking

Ver my answer sobre una cuestión similar para más discusión.

Cuestiones relacionadas