简体   繁体   English

PostgreSQL JDBC 驱动轮作物双倍价值

[英]PostgreSQL JDBC Driver rounds crops double value

I'm using PostgreSql 9.3 together with the postgresql-9.3-1101 JDBC Driver.我正在使用 PostgreSql 9.3 和 postgresql-9.3-1101 JDBC 驱动程序。 And there is a really strange behavior with the PreparedStatements . PreparedStatements有一个非常奇怪的行为。

Here is the example: First I create a test table:这是示例:首先我创建一个测试表:

CREATE TABLE double_test
(
   id          numeric(18)     NOT NULL
);

After that that i run following code:之后我运行以下代码:

DecimalFormat df = new DecimalFormat("0");
try {
    conn = BeanUtils.getBean("dataSource", DataSource.class).getConnection();
    conn.setAutoCommit(false);
    conn.createStatement().execute("DELETE from double_test ");
    conn.commit();
    PreparedStatement stmt = conn.prepareStatement("INSERT INTO double_test (id )VALUES (?)");
    double input = 1234567890123456d;
    System.out.println("Input:" + df.format(input));
    stmt.setDouble(1, input);
    stmt.execute();
    conn.commit();

    ResultSet rs = conn.createStatement().executeQuery("SELECT id FROM double_test ");
    rs.next();
    System.out.println("Output:" + df.format(rs.getDouble(1)));
    rs.close();
} catch (SQLException e1) {
    throw new RuntimeException(e1);
} finally {
    try {
        conn.close();
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

The output of the code will be:代码的 output 将是:

Input: 1234567890123456
Output:1234567890123460

Which gets me very confused, after the 15. digit the Postgres JDBC Driver starts to round.这让我很困惑,在 15 位数字之后,Postgres JDBC Driver 开始四舍五入。 The inserted data gets corrupted, without any further notice!插入的数据已损坏,恕不另行通知!

Did I miss anything here?我在这里错过了什么吗? Has my code any errors?我的代码有错误吗?

Or is this a bug in the Driver?或者这是驱动程序中的错误? If so, I really wonder that no one noticed this yet.如果是这样,我真的很奇怪还没有人注意到这一点。

Maybe working with BigDecimal will prevent the data from corrupting, but this is just a workaround.也许使用BigDecimal可以防止数据损坏,但这只是一种解决方法。

There is a two problem.有两个问题。

First from Double class:首先来自Double class:

System.out.println(0.1 + 0.2); //output 0.30000000000000004

So usually don't use Double (also Float ).所以通常不要使用Double (也是Float )。

Second from jdbc driver, it is triying to save database with toString method which class related with org.postgresql.jdbc.PgPreparedStatement .第二个来自 jdbc 驱动程序,它正在尝试使用 toString 方法保存数据库,其中 class 与org.postgresql.jdbc.PgPreparedStatement相关。

Check this:检查这个:

System.out.println(new BigDecimal("0.00000072")); // print 7.2E-7

It is equal but when Jdbc driver save with this, some precisions corrupt, so I replace它是相等的,但是当 Jdbc 驱动程序用这个保存时,一些精度损坏了,所以我替换了

    public void setBigDecimal(@Positive int parameterIndex, @Nullable BigDecimal x)
            throws SQLException {
        setNumber(parameterIndex, x); // It is using toString method
    }

with this:有了这个:

public void setBigDecimal(@Positive int parameterIndex, @Nullable BigDecimal x)
        throws SQLException {
    checkClosed();
    if (x == null) {
        setNull(parameterIndex, Types.DECIMAL);
    } else {
        bindLiteral(parameterIndex, x.toPlainString(), Oid.NUMERIC); //now using toPlainString
    }

}

If you really want to use Double or Float you can fix like this changes.如果你真的想使用DoubleFloat ,你可以像这样修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM