Frage

Ich bin mit Hibernate als meine JPA-Provider damit zu einem Fortschritt Datenbank verbinden. Wenn ein NaN Wert beibehalten wird es viele Probleme verursacht - es verhindert, dass die Reihe von unter bestimmten Umständen gelesen werden. Gibt es eine Möglichkeit, um die Standard-Doppeltyp Persistenz Haken in konvertieren NaN (und wahrscheinlich + und - unendlich) auf einen anderen Wert? Dabei spielt es keine Rolle, ob die NaN oder unendlich Informationen verloren gehen, ich will nur eine lesbare Zeile!

Ich weiß, dass ich etwas tun könnte:

@Column(name = "doubleColumn")
public double getDoubleColumn() {
    return PersistedDouble.convert(doubleColumn);
}

Aber ich mache mir Sorgen um Wartung, wie die manuell für alle in der Datenbank abgebildet verdoppelt hinzugefügt werden müssen.

War es hilfreich?

Lösung

Mein erster Eindruck von diesem wäre für den Typen zu suchen, die den Ruhezustand bleibt double wie. So können Sie die set(...) Methode in DoubleType . Das würde bedeuten, aber, dass Sie jeden Double Typ mit @org.hibernate.annotations.type(type="myDouble") zu annotieren müssten, nachdem Sie definiert haben „myDouble“ mit @org.hibernate.annotations.TypeDef in Paket-info - ich glaube, Sie wollen das alles für Wartung vermeiden (darüber hinaus würden Sie in die gehen müssen Herz von Hibernate).

Andere Tipps

könnten Sie ändern sich winter. Alles, was Sie tun müssen, ist die Klasse DoubleType ändern.

Natürlich würden Sie dann pflegen müssen diesen Patch als Hibernate entwickelt, aber es ist in einer einzigen, ziemlich stabil Klasse bedenkt, dass dies könnte einfacher sein, als ein Usertype für jeden Doppel in Ihrem Domain-Modell angeben.

Im Anschluss an diese Diskussion , ich das Gefühl habe, dass Hibernate bietet keine Möglichkeit, NaN in etwas anderes zu konvertieren. Ich denke, müssen Sie NaN Werte früher verhindern, noch bevor sie auf die Bohne Membervariablen geschrieben sind (wie das Hinzufügen Schutz / Conversion-Code auf die Setter).

Bearbeiten

Ich fürchte, die beste Lösung unangenehm ist guard-Code zu verwenden und, was noch schlimmer ist, eine zusätzliche Spalte auf dem Tisch ist, zu kennzeichnen, ob der Wert eine Zahl ist oder nicht. Was sicherlich werden die Abfrage und Einfügeoperationen erschweren. Aber Sie müssen NaN in der Datenbank und Sie können nicht kämpfen, um die JDBC-Treiber / Datenbank richtig zu verhalten (und akzeptieren NaN als gültige Eingaben für Zahlenfelder).

habe ich die Usertype Lösung am Ende aber das Wartungsproblem mit einem Unit-Test gelöst. Die Typklasse ist wie folgt:

public class ParsedDoubleType extends DoubleType {
    private static final long serialVersionUID = 1L;

    @Override
    public void set(PreparedStatement st, Object value, int index) throws SQLException {
        Double doubleValue = (Double) value;
        if (doubleValue.isInfinite() || doubleValue.isNaN()) {
            Logger.getLogger(ParsedDoubleType.class).warn("Attempted to send a NaN or infinity value to the database " 
                + "- this is not supported.\nStatement=" + st + " valueIndex=" + index);
            doubleValue = Double.valueOf(0);
        }
        super.set(st, doubleValue, index);
    }
}

Der Unit-Test ist grob (einige Details der Kürze entfernt):

Ejb3Configuration hibernateConfig = new Ejb3Configuration().configure("InMemoryDatabasePersistenceUnit", null);
for (Iterator<?> iterator = hibernateConfig.getClassMappings(); iterator.hasNext();) {
    PersistentClass clazz = (PersistentClass) iterator.next();
    Iterator<?> propertyIterator = clazz.getPropertyIterator();
    while (propertyIterator.hasNext()) {
        if (property.getType().equals(Hibernate.DOUBLE)) {
            Assert.fail("Raw double type found. Annotate with @Type(type = \"package.ParsedDoubleType\")\n" 
                + "Class " + clazz + " property " + property);
        }
    }
}

Ich hatte genau das gleiche Problem, und mit der Führung dieser Lösungen, ich auch bereit, eine benutzerdefinierten Typ-Klasse erweitern DoubleType. Innerhalb dieser Klasse I umgewandelt NaN-Wert auf null bei der eingestellten Funktion und umgekehrt für die get-Funktion, da null für meine Datenbankspalte in Ordnung ist. Ich habe auch die Zuordnung für NaN mögliche Spalten der benutzerdefinierten Typklasse. Diese Lösung funktionierte perfekt für Hibernate 3.3.2.

Leider nach Ruhezustand zu 3.6.10 aktualisieren, es funktioniert nicht mehr. Um es noch einmal zu machen arbeiten, ersetzt ich den benutzerdefinierten Typen von DoubleType erstreckt Usertype zu implementieren.

Das wichtige Datentyp Funktion Implementierungen sollte wie folgt aussehen:

private int[] types = { Types.DOUBLE };

public int[] sqlTypes()
{
    return types;
}

@SuppressWarnings("rawtypes")
public Class returnedClass()
{
    return Double.class;
}

Und hier sind die erhalten und stellen Funktionen:

public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException
{
    Double value = rs.getDouble(names[0]);
    if (rs.wasNull())
        return Double.NaN;
    else
        return value;
}

public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException
{
    Double dbl = (Double) value;
    if ((dbl == null) || (Double.isNaN(dbl)))
        ps.setNull(index, Types.DOUBLE);
    else
        ps.setDouble(index, dbl);
}

Sorry, aber die Beurteilung von Ihren Beispielen und Ihre Frage, die Sie haben tatsächlich Probleme Java-Persistenz zu verstehen. Datenbank-Entitäten sind selbstverwaltete über Getter und Setter - diese jede Validierung tun können Sie sie haben möchten. Wenn Sie wirklich Attribute, ohne sie zu setzen, sind Sie nicht Kernkonzepte der objektorientierten Entwicklung und Persistenz - verwalteten Einheiten im Besonderen. Mir scheint, müssen Sie Ihr Projekt neu zu konstruieren, Probleme wie diese, die ein sicheres Zeichen von grundlegender Konstruktionsfehler sind ... nur ein paar Ratschläge hier geben - und das ist die Lösung:

@Column(name="doubleColumn"}
private Double doubleColumn = Double.NaN  //yes, this is intentional. Verily.

public void setDouble(Double d)
{
    if(d.isNan || d.isInfinite()
    {
       //do something nice here
    }
    else
       this.doubleColumn = d;
}
public Double getDouble()
{
   return !this.doubleColumn.isNaN() && !this.doubleColumn.isInfinite() ? this.doubleColumn : new Double();
}

.... So einfach ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top