我有一个很长的事务,我正在尝试使用JDBC为PostgreSQL执行。在JDBC中我不能使用COMMIT
和ROLLBACK
,所以我试图在Java代码中实现我想要的行为......
try {
con = DriverManager.getConnection(url, user, password);
con.setAutoCommit(false);
Statement st = con.createStatement();
st.execute(myHugeTransaction);
con.commit();
} catch (SQLException ex) {
try {
con.rollback();
} catch (SQLException ex1) {
// log...
}
// log...
}
对于小语句,这非常有效,但对于单个事务中大约10K语句的大型语句,这在con.commit
行中失败
org.postgresql.util.PSQLException: ERROR: kind mismatch among backends. Possible last query was: "COMMIT" kind details are: 0[C] 1[N: there is no transaction in progress]
有趣的是,如果我用st.getWarnings();
捕获SQL警告,我可以看到数据库实际上正在处理我发送的整个脚本,就在提交时,它都会失败。
修改
也许我没有做到这一点,所以有两个问题:
Statement.execute()
?答案 0 :(得分:0)
老实说,如果这是一个SQL脚本,你最好不要对psql进行shell转义。这是处理这个问题的最好方法。总的来说,我有太多令人不快的惊喜来自试图解析SQL代码并针对数据库运行它的人。这种疯狂的方式。
你说“较小的脚本”,这使我得出结论你正在做一些事情,比如设置一个数据库(或升级一个,但由于没有查询,这样做的可能性较小)。通过shell转义使用psql,不要回头看。这真的是最好的方式。
我想如果你必须,可以尝试在你的脚本中添加显式的BEGIN和COMMIT。
我不确定为什么它似乎是隐式提交事务。你已正确设置自动提交。您的代码中没有明显的问题。你有可能有一个旧的或错误的JDBC驱动程序?如果没有,我建议使用PostgreSQL JDBC驱动程序项目提交错误报告。