【问题标题】:Storing Java Double Infinity and NaN values to MS SQL 2008 database将 Java Double Infinity 和 NaN 值存储到 MS SQL 2008 数据库
【发布时间】:2012-05-16 16:09:12
【问题描述】:

在我们的业务逻辑中,我们必须处理正负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 值时得到以下堆栈跟踪:

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

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

【问题讨论】:

    标签: java sql-server hibernate double infinity


    【解决方案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;
    }
    

    【讨论】:

    • 这似乎是解决问题的正确方法。唯一的限制是,由于该值在数据库中为 VARCHAR,因此您可能无法在 SQL 中对这些值执行计算。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 2013-03-12
    相关资源
    最近更新 更多