Stockage des valeurs Java Double Infinity et NaN dans la database MS SQL 2008

Dans notre logique métier, nous devons gérer des valeurs Double.Infinity positives et négatives ainsi que des valeurs Double.NaN .

Nous devons stocker ces valeurs dans la database Microsot SQL Server 2008. Le problème est que Microsot SQL Server ne supporte pas les valeurs infinity ou nan. ( Description du problème pour SQL Server 2005 , également applicable pour MS SQL Server 2008).

Nous utilisons Hibernate 3.6.7 comme implémentation JPA et la version 4.0.2206.100 du pilote Microsoft sqljdbc4.

Nous avons essayé de résoudre ce problème en définissant la définition de colonne de l'entité JPA sur VARCHAR comme ceci

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

Cela ne semble pas avoir d'effet, même si la définition de colonne est correctement modifiée en VARCHAR dans la database. Il semble que la valeur infinity est capturée dans la validation du pilote JDBC puisque nous obtenons la stacktrace suivante en essayant d'INSERT Double.Infinity :

 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 

Toutes les idées pour contourner ce problème sont les bienvenues.

    Voici une solution de contournement simple pour ce problème: Utilisez Ssortingng pour le type de champ et effectuez la conversion dans les getters et les setters. De cette façon, vous n'avez pas à modifier votre logique métier et la logique de transformation réelle est bien encapsulée.

     // Column definition is not a necessity here @Column(columnDefinition = "VARCHAR(40)") private Ssortingng foo; public Double getFoo() { return this.foo != null ? Double.valueOf(this.foo) : null; } public void setFoo(Double d) { this.foo = d != null ? d.toSsortingng() : null; }