【问题标题】:PreparedStatement doesn't replace placeholder for setBytesPreparedStatement 不会替换 setBytes 的占位符
【发布时间】:2015-11-10 10:25:49
【问题描述】:

目前我在 Java 中遇到了 PreparedStatements 的一个奇怪问题。

我正在生成一个带有 9 个参数的 SQL 语句,以将信息存储到我的 postgres 数据库中(整数、带时区的时间戳、双精度、双精度、双精度、双精度、带时区的时间戳、带时区的时间戳和 bytea)。

问题出现在最后一列(bytea 格式)。我想存储一个序列化的对象。序列化工作正常,并且使用相同的代码,我已经将对象存储到不同数据库的另一个表中。

这是我正在使用的代码的(重要部分):

String sql = "INSERT INTO archiv_database VALUES(?,?,?,?,?,?,?,?,?);";
Connection con;
PreparedStatement preparedStatement;        
long millis = System.currentTimeMillis();
byte[] data = KryoIO.kryoSerializeObjectToBytes(myObject);

GregorianCalendar calendar = new GregorianCalendar();

try {
        con = ResourcesHelper.getConnectionToPGDatabase("jdbc:postgresql://ipadress/db", "user", "password");
        preparedStatement = con.prepareStatement(sql);

        preparedStatement.setInt(1, 0);
        preparedStatement.setTimestamp(2, new Timestamp(millis), calendar);
        preparedStatement.setDouble(3, 0);
        preparedStatement.setDouble(4, 0);
        preparedStatement.setDouble(5, 0);
        preparedStatement.setDouble(6, 0);
        preparedStatement.setTimestamp(7, myObject.getValidFrom(), calendar);
        preparedStatement.setTimestamp(8, myObject.getValidUntil(), calendar);
        preparedStatement.setBytes(9, data);

        if(preparedStatement.toString().contains("?")){
            System.err.println("Statement still contains a ? and can't be executed");
        } else{
            int n = preparedStatement.executeUpdate();
            System.out.println("Stored into " + n + " row(s).");
        }

        preparedStatement.close();
        con.close();

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

在调用 setBytes 方法之前,该语句已正确准备。那里的数据没有放入语句中。占位符在之后仍然存在。我已经用调试模式检查了数据。序列化工作没有错误,并且 byte[] 充满了数据。以下是所有 9 种方法后语句的样子:

INSERT INTO archiv_database VALUES(0,'2015-11-10 11:19:24.430000 +01:00:00',0.0,0.0,0.0,0.0,'2015-11-03 14:04:24.000000 +01:00:00','2015-11-03 14:07:04.000000 +01:00:00',?)

语句本身正在运行。如果我填写一些虚拟数据(对象为空),我已经自己通过 PGAdmin III 对其进行了测试。但是你可以看到最后一个占位符仍然存在并且没有被替换,即使数据变量保存了数据。

也许你们中的一些人知道如何解决这个问题。如果您需要更多信息,请询问。

感谢您的帮助

【问题讨论】:

  • 什么是字段类型,尤其是大小? data 的长度是多少?尝试一个短数组。
  • 您意识到if(preparedStatement.toString().contains("?")) 是特定于驱动程序的黑客,对吧?此外,它可能并不总是有效 - 具体来说,请考虑如果在其 value 中绑定带有问号的字符串变量会发生什么。
  • 当前测试的字节数组长度为 346。但存储在其他项目中也是可能的。所以这应该没有什么大问题。我删除了占位符的检查。我只是添加它来检查它是否总是在那里结束。该语句仍然无效。
  • 如果您运行executeUpdate() 而不对? 进行(无用的)检查,会发生什么 - 我很确定它会起作用。 toString() 方法返回没有 ? 的字符串的假设是完全错误的(并且没有任何 JDBC 文档支持)
  • 我和 a_horse_with_no_name 在一起,只需执行更新,它可能会工作。 toString() 方法可能不知道如何,或者只是不想输出 byte[] 数据。

标签: java postgresql prepared-statement


【解决方案1】:

感谢 a_horse_with_no_name 提供有关提交的信息。似乎我从同事那里使用的连接助手类没有自动提交,所以我需要调用 con.commit() 方法来正确存储所有内容。

谢谢大家的帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2013-01-24
    相关资源
    最近更新 更多