将Java Double Infinity和NaN值存储到MS SQL 2008数据库

时间:2012-05-08 07:06:24

标签: java sql-server hibernate double infinity

在我们的业务逻辑中,我们必须处理正面和负面Double.Infinity值以及Double.NaN值。

我们必须将这些值存储到Microsot SQL Server 2008数据库中。问题是Microsot SQL Server不支持infinity或nan值。 (Problem description for SQL Server 2005,也适用于MS SQL Server 2008)。

我们使用Hibernate 3.6.7作为JPA实现,使用Microsoft的sqljdbc4驱动程序版本4.0.2206.100。

我们尝试通过将JPA实体的列定义设置为VARCHAR来解决此问题,就像这样

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

这似乎没有任何影响,即使列定义已正确更改为数据库中的VARCHAR。看起来无限值是在JDBC驱动程序的验证中捕获的,因为我们在尝试INSERT Double.Infinity值时得到以下stacktrace:

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

欢迎任何有关如何解决此问题的想法。

1 个答案:

答案 0 :(得分:1)

以下是此问题的简单解决方法: 使用String作为字段类型,并在getter和setter中进行转换。 这样您就不必更改业务逻辑,并且可以很好地封装实际的转换逻辑。

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