2012-05-08 9 views
7

In unserer Geschäftslogik müssen wir positive und negative Double.Infinity Werte sowie Double.NaN Werte behandeln.Speichern von Java Double Infinity und NaN Werten in MS SQL 2008 Datenbank

Wir müssen diese Werte in Microsot SQL Server 2008-Datenbank speichern. Das Problem ist, dass Microsot SQL Server keine Unendlichkeits- oder Nanoparameter unterstützt. (Problem description for SQL Server 2005, gilt auch für MS SQL Server 2008).

Wir verwenden Hibernate 3.6.7 als unsere JPA-Implementierung und Microsoft sqljdbc4 Treiberversion 4.0.2206.100.

Wir haben versucht, dieses Problem zu lösen, indem in VARCHAR Einstellung Spaltendefinition der PPV Einheit wie diese

@Column(columnDefinition = "VARCHAR(40)") 
private Double foo; 

Dies scheint nicht irgendeine Wirkung zu haben, obwohl Spaltendefinition richtig VARCHAR in der Datenbank geändert wird. Es scheint, dass die Unendlichkeit Wert wird in JDBC-Treiber der Validierung gefangen, da wir die folgende Stacktrace beim Versuch Double.Infinity Wert einfügen:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 6 (""): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision. 
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) 
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) 
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94) 
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57) 
    ... 79 more 

Irgendwelche Ideen, wie um dieses Problem zu arbeiten, sind willkommen.

Antwort

1

Hier ist eine einfache Problemumgehung für dieses Problem: Verwenden Sie String für Feldtyp und die Konvertierung in Getter und Setter. Auf diese Weise müssen Sie Ihre Geschäftslogik nicht ändern und die eigentliche Transformationslogik wird gut gekapselt.

// Column definition is not a necessity here 
@Column(columnDefinition = "VARCHAR(40)") 
private String foo; 

public Double getFoo() { 
    return this.foo != null ? Double.valueOf(this.foo) : null; 
} 

public void setFoo(Double d) { 
    this.foo = d != null ? d.toString() : null; 
} 
+1

Dies scheint wie eine geeignete Problemumgehung für das Problem. Da der Wert in der Datenbank als VARCHAR angegeben ist, können Sie möglicherweise keine Berechnungen für die Werte in SQL ausführen. – Spaideri