【发布时间】: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