2012-05-08 20 views
7

Nella nostra logica aziendale dobbiamo gestire i valori positivi e negativi Double.Infinity nonché i valori Double.NaN.Memorizzazione dei valori Java Double Infinity e NaN nel database MS SQL 2008

Dobbiamo memorizzare questi valori nel database di Microsot SQL Server 2008. Il problema è che Microsot SQL Server non supporta valori infinito o nan. (Problem description for SQL Server 2005, applicabile anche per MS SQL Server 2008).

Stiamo utilizzando Hibernate 3.6.7 come implementazione JPA e la versione di driver sqljdbc4 di Microsoft 4.0.2206.100.

Abbiamo cercato di risolvere questo problema impostando definizione di colonna dell'APP entità VARCHAR come questo

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

Questo non sembra avere alcun effetto, anche se la definizione di colonna è correttamente modificato in VARCHAR nel database. Sembra che il valore infinito e 'colto in convalida di driver JDBC poiché otteniamo la seguente stacktrace quando cercando di inserire Double.Infinity valore:

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 

Delle idee come risolvere questo problema sono i benvenuti.

risposta

1

Ecco una soluzione semplice per questo problema: Utilizzare String per il tipo di campo ed eseguire la conversione in getter e setter. In questo modo non è necessario modificare la logica aziendale e l'effettiva logica di trasformazione è incapsulata in modo corretto.

// 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

Sembra una soluzione alternativa per risolvere il problema. L'unica limitazione è che poiché il valore è come VARCHAR nel database, potrebbe non essere possibile eseguire calcoli per i valori in SQL. – Spaideri

Problemi correlati