7

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

我们必须将这些值存储到 Microsot SQL Server 2008 数据库中。问题是 Microsot SQL Server 不支持 infinity 或 nan 值。(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 驱动程序的验证中被捕获,因为我们在尝试插入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

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

4

1 回答 1

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;
}
于 2012-05-09T08:53:59.327 回答