2016-03-30 7 views
0

Das Problem ist, dass ich ein falsches Datum von der Ladefunktion von DAO bekomme.Wie verhindert man, dass der Ruhezustand falsche Daten lädt?

Das beobachtete Datum wird in der PostgreSQL-Datenbank gespeichert (stammt aus der Birthdate-Spalte aus der User-Tabelle) und entspricht 1982-03-28. Es wird manchmal als 1982-03-27 abgerufen. Ich habe einen Tipp von erfahreneren Benutzern bekommen und sie sagen, dass es irgendwie mit Zeitzonenproblemen zusammenhängt.

Die falschen Werte stammen aus der Instanz der Klasse java.util.Date. Ich erhalte sie am Objekt der Kalenderklasse. Als ich nenne das die Kleinen:

calendar.getTimeZone().getDisplayName() 

es gibt

Central European Time 

Der Typ des Birth Spalte ist:

birthTIMESTAMP OHNE ZEITZONE

Der Wert der Die in der postgresql.conf-Datei festgelegte Zeitzonenvariable entspricht Polen.

Die innere Implementierung sieht die Load-Methode wie folgt aus:

public T load(ID aPrimaryKey, boolean aLock) 
{ 
    if (aPrimaryKey == null) { 
     throw new IllegalArgumentException("Parameter aPrimaryKey can't be null!"); 
    } 
    preLoad(aPrimaryKey); 
    T entity; if (aLock) { 
     entity = _session.load(getEntityClass(), aPrimaryKey, LockMode.UPGRADE); 
    } else 
     entity = _session.load(getEntityClass(), aPrimaryKey); 
    postLoad(entity); 

    return entity; 
} 

Meine Datenbank Version

PostgreSQL 9.4.4 auf x86_64-unknown-linux-gnu ist, von gcc (Debian 4.9 .2-10) 4.9.2, 64-Bit-

I verwenden

Hibernate-Core-3.6.0.Final.jar

Meine Entitätsklasse sieht wie folgt aus (einige Felder hat):

import javax.persistence.Column; 

@javax.persistence.Entity 
@javax.persistence.Table(name="User") 
@javax.persistence.SequenceGenerator(name="userId", sequenceName="user_id_seq", allocationSize=1) 
public class User { 

    @javax.persistence.Id 
    @Column(name="Id", nullable=false) 
    @javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO, generator="userId") 
    private long id; 

    @Column(name="Name") 
    private String firstName; 

    public User(String firstName, java.util.Date birthDate, java.util.Date registrationDate) 
    { 
     this.firstName = firstName; 
     this.birthDate = birthDate; 
     this.registrationDate = registrationDate; 
    } 

    @Column(name="BirthDate") 
    @javax.persistence.Temporal(javax.persistence.TemporalType.DATE) 
    private java.util.Date birthDate; 

    @Column(name="RegistrationDate", nullable=false) 
    @javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP) 
    private java.util.Date registrationDate; 

    public String toString() 
    { 
     return firstName + " should clean himself..."; 
    } 

    public User() {} 
} 

ich die Art von birthdate Feld TIMESTAMPTZ geändert - dann scheint alles gut zu funktionieren. Aber wie löst man das Problem, ohne den Datentyp der Spalte zu ändern? Hast du irgendwelche Tipps?

+0

Wie speichert PG es als Zeitstempel und nicht als Datum? Seltsam. Können Sie die Spaltendefinition ändern, um sie als Datum und nicht als Zeitstempel zu speichern? –

+0

@NeilMcGuigan Ich könnte, aber ich habe bereits einige tausend Benutzer in der Datenbank, also müsste ich die Geburtsdaten für alle von ihnen ändern (Ich werde prüfen, wie Datum von Timestamp in PostgreSQL abweichen, weil ich nicht ganz sicher bin, wie zwischen diesen beiden Arten konvertieren). – y434y

Antwort

0

Ich denke, das Problem könnte sein, dass Ihr System auf CET eingestellt ist, aber Polen ist derzeit auf CEST (und Pg honoriert DST).

Ein paar Dinge, die Sie tun können:

  • Verwenden SET TIME ZONE timezone; zu Beginn jeder Sitzung um sicherzustellen, dass es Ihren Client übereinstimmt.

  • Verwenden Sie AT TIME ZONE, wenn Sie die Werte - oder die Funktion timezone(zone, timestamp) - für den Client auswählen.

  • Lassen Sie den Wert bei der Auswahl auf timestamptz umwandeln, damit die TZ-Informationen erhalten bleiben (nicht wirklich sicher über diese).

Aber wirklich, es ist viel besser, immer timestamptz zu verwenden, um Zeit zu speichern.

Um Ihre Frage aus dem Kommentar zu antworten: Sie können nur timestamp/tz Werte an den date Typen (birthdate::date) gegossen. date s haben keine Zeitinformationen und sind nicht von der Zeitzone abhängig, so dass Sie immer den Wert erhalten, wie er ist.

Dies kann eigentlich mehr Sinn machen - Sie wahrscheinlich tun wollen Geburtsdaten in ihren ursprünglichen Zeitzonen (dh wie die Benutzer sie eingegeben), nicht in die aktuelle TZ umgewandelt sehen.

Verwandte Themen