Serialisierungsdatum in Java

7

Ich gebe einige Objekte über den Webservice weiter und einige davon enthalten java.sql.Date. Weil Date keinen leeren Konstruktor hat, möchte es nicht serialisiert werden.

Der erste Teil einer Frage ist einfach: Was ist der beste Weg, ein Datum zwischen Kunde und Service zu übergeben?

Der zweite Teil ist etwas kniffliger: Sobald ich entscheide, wie man Daten umgeht, kann ich offensichtlich transiente Daten deklarieren und eine Wrapper-Klasse erstellen, um Daten als String oder was auch immer weiterzugeben, aber dieselbe Lösung so transparent wie möglich auf mehrere Klassen anwenden das Datum enthalten?

(Ich habe die Vermutung, dass DynamicProxy-Ding eine Lösung sein könnte, aber das Lesen der Dokumentation auf Suns Website war nicht sehr hilfreich, also wenn es wirklich etwas in dieser Richtung ist, wäre eine Klärung wünschenswert)

Edit: Ich habe falsche Frage gestellt, sorry (ein Missverständnis zwischen mir und Kollegen, was eigentlich ein Problem ist). Problem tritt aufgrund der Deserialisierung auf. Sobald ich ein Datum im XML-Format habe, versucht es sich als GregorianCalendar zu deserialisieren. Der andere Teil einer Frage bleibt immer noch: Was ist der beste Weg, um etwas zu erhalten (lange Zeitstempel oder GregorianCalendar) und konvertieren Sie es in SQL-Datum, ohne 10 verschiedene Wrapper für 10 verschiedene Klassen zu machen. Ich benutze eine NetBeans für Code und WSDL-Generation.

    
Slartibartfast 22.09.2008, 12:32
quelle

12 Antworten

8

Joda-Zeit

Die Date-Klasse hat eine klobige API. Eine bessere Umsetzung ist Joda-Time .

ISO 8601

Joda-Time ermöglicht es Ihnen auch, Ihr Datum in ein ISO 8601 Standardformat zu konvertieren (jjjj-mm-ddTHH: MM: SS.SSS). Die Verwendung dieses Standards beim Verschieben von Daten vom Server auf seinen Client hat den Vorteil, dass das vollständige Datum in einem lesbaren Format enthalten ist. Wenn Sie zum Beispiel JAXB verwenden, ist die XML-Darstellung eines Datums auch dieser ISO-Standard. (Siehe die XMLGregorianCalendar-Klasse)

    
JeroenWyseur 22.09.2008 12:52
quelle
6

Das Serialisieren der von Date.getTime () zurückgegebenen langen Maustaste, wie zuvor vorgeschlagen, funktioniert. Sie sollten jedoch beachten, dass sich das Datum, das Sie auf der anderen Seite rekonstruieren, anders verhält, wenn sich Ihr Server in einer anderen Zeitzone als der Client befindet. Wenn Sie genau dasselbe Datumsobjekt rekonstruieren möchten, müssen Sie auch Ihre Zeitzone senden (TimeZone.getID ()) und sie verwenden, um das Datum auf der anderen Seite zu rekonstruieren.

    
entzik 22.09.2008 12:45
quelle
3

Um den ersten Teil Ihrer Frage zu beantworten, würde ich eine Zeichenfolge im ISO-8601-Format vorschlagen (dies ist ein Standard für das Kodieren von Daten).

Für den zweiten Teil bin ich nicht sicher, warum Sie eine Proxy-Klasse benötigen würden? Oder warum Sie die Datumsklasse erweitern müssten, um dies zu unterstützen. z.B. Wüsste Ihr Webdienst nicht, dass ein bestimmtes Feld ein Datum ist und die Konvertierung von Datum zu String und zurück erfolgt? Ich brauche ein wenig mehr Informationen.

    
Chris Gow 22.09.2008 13:08
quelle
2

java.sql.Date erweitert java.util.Date

Verwenden Sie einfach getTime (), um den langen Wert daraus zu erhalten. Dies kann serialisiert werden und ein neues java.sql.Date (lang) oder neues java.util.Date (lang) daraus am anderen Ende konstruiert werden.

    
cagcowboy 22.09.2008 12:34
quelle
1

Ich habe in die Implementierung von java.sql.Date geschaut und wie ich es sehe java.sql.Date ist Serializable als Erweiterung von java.util.Date.

    
boutta 22.09.2008 12:47
quelle
1

Ein Vorbehalt mit java.sql.Date, das mich vor kurzem gebissen hat, ist, dass es die Zeitabschnitte (Stunden, Minuten, Sekunden usw.) nicht nur den Datumsteil speichert. Wenn Sie den vollständigen Zeitstempel möchten, müssen Sie java.util.Date oder java.sql.Timestamp

verwenden     
Matt 22.09.2008 18:26
quelle
1

Ich werde auf die richtige Antwort von JeroenWyseur eingehen.

ISO 8601

Das ISO 8601 Standardformat ist absolut der beste Weg, um einen Datum-Uhrzeit-Wert für den Datenaustausch zu serialisieren. Das Format ist unzweideutig, intuitiv für Menschen in allen Kulturen und zunehmend auf der ganzen Welt verbreitet. Einfach zu lesen für Mensch und Maschine.

%Vor%

Das erste Beispiel hat einen Offset von zwei Stunden vor UTC. Das zweite Beispiel zeigt die allgemeine Verwendung von Z ("Zulu") zur Angabe von UTC, kurz für +00:00 .

Joda-Zeit & amp; java.time

Das java.util.Date & amp; .Kalender-Klassen, die mit Java gebündelt sind, sind bekanntermaßen mühsam, verwirrend und fehlerhaft. Vermeide sie. Verwenden Sie stattdessen entweder:

  • Joda-Zeit Bibliothek
  • Paket java.time, eingebaut in Java 8, inspiriert von Joda-Time, definiert durch JSR 310.

Standardmäßig verwenden beide Bibliotheken ISO 8601 zum Parsen und zum Generieren von String-Darstellungen von Datums- und Uhrzeitwerten.

Beachten Sie, dass java.time das ISO 8601-Format erweitert, indem Sie den richtigen Namen der Zeitzone hinzufügen, z. co_de%.

Durchsuchen Sie StackOverflow.com nach vielen hundert Fragen und Antworten mit viel Diskussions- und Beispielcode für diese beiden Bibliotheken.

Vermeiden Sie Count-From-Epoch

Einige der anderen Antworten empfehlen die Verwendung einer Zahl, eine Anzahl von Epochen . Dieser Ansatz ist nicht praktikabel. Es ist nicht selbstverständlich. Es ist nicht für Menschen lesbar, macht das Debugging mühsam und frustrierend.

Welche Nummer ist es, ganze Sekunden wie in Unix üblich, Millisekunden in java.util.Date & amp; Joda-Time, Mikrosekunden, die üblicherweise in Datenbanken wie Postgres oder Nanosekunden verwendet werden, die in java.time Paket ?

Welches der paar Dutzend Epochen , das erste Mal von 1970 in Unix verwendet, Jahr 1 verwendet in .Net & amp; Go, "Januar 0, 1900" verwendet in Millionen (Milliarden?) Von Excel & amp; Lotus-Tabellen oder 1. Januar 2001 von Cocoa verwendet?

Siehe meine Antwort zu einer ähnlichen Frage für weitere Diskussionen.

    
Basil Bourque 20.01.2015 03:52
quelle
0

Sie benötigen keinen Standardkonstruktor (leer), um das Datum serialisieren / deserialisieren zu können (entweder java.sql.Date oder java.util.Date). Während der Deserialisierung wird der Konstruktor nicht aufgerufen, sondern die Attribute des Objekts werden direkt auf Werte aus serialisierten Daten gesetzt, und Sie können das Objekt so verwenden, wie es seit der Deserialisierung ist.

    
Andreas Bakurov 22.09.2008 12:43
quelle
0

Sie können einen Encoder verwenden und dekodieren, um Ihre Objekte zu serialisieren und zu deserialisieren.

Hier ist ein Beispiel, das die Klasse SWT Rectangle serialisiert:

%Vor%     
paul 22.09.2008 12:45
quelle
0

Erstens, wenn Sie Webdienste verwenden, bedeutet dies, dass Sie in XML serialisieren und nicht Ihre normale Java-Serialisierung (sondern eine andere Bibliothek zum Marshalling und Unmarshalling). Daher fehlen der Frage einige Informationen.

Zweitens, wenn Sie die Kontrolle über Ihren InputStream & amp; OutputStream versuchen, ObjectOutputStream und ObjectInputStream zu erweitern und überschreiben replaceObject () und resolveObject () und dann können Sie die Serialisierung für java.sql.Date implementieren.

    
Shimi Bandiel 22.09.2008 12:36
quelle
0

java.sql.Date implementiert bereits Serializable, so dass es nicht implementiert werden muss: -)

Was Ihre Hauptfrage betrifft, bin ich tief in JAXB verliebt, da ich fast jedes XML in ein Objekt umwandeln kann. Es könnte sich also lohnen, einen Blick darauf zu werfen.

    
Ioannis 22.09.2008 13:43
quelle
0

Hmmm ... Ich kann mir keinen Grund vorstellen, warum eine serialisierte Objektinstanz (serialisiert über den Standard-Java-Mechanismus) sich selbst als Instanz einer anderen Klasse deserialisieren sollte, da die Klasseninformation ein fester Bestandteil der serialisierten Daten sein sollte .

Es ist also entweder ein Problem Ihres (De-) Serialisierungsframeworks oder das Framework akzeptiert irgendein "datumsähnliches" Objekt auf dem "sendenden Ende" (Kalender, java.util.Date usw. - also java.sql. Datum auch, da es java.util.Date erweitert, "serialisiert" es zu einem String in einem gemeinsamen Datumsformat (so dass die Typinformationen verloren gehen) und "deserialisiert" es zurück zu einem Kalenderobjekt auf der Empfängerseite.

Ich denke, der einfachste Weg, um zu java.sql.Date zu gelangen, ist ein

%Vor%

wo Sie eine java.sql.Date benötigen, aber den GregorianCalendar von der "Deserialisierung" zurückholen.

    
Argelbargel 22.09.2008 14:22
quelle