1

我有一个很长的事务,我正在尝试使用 JDBC for PostgreSQL 执行。在 JDBC 中我不能使用COMMITand 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]

有趣的是,如果我捕捉到 SQL 警告,st.getWarnings();我可以看到数据库实际上正在处理我发送的整个脚本,就在提交时,一切都失败了。

顺便说一句,交易完全没问题。我将它的精确副本写入一个文件,我可以通过将它复制到 pgAdmin 来运行它而不会出错。希望你能在那个问题上帮助我,我已经搜索和测试了几个小时了......

编辑

也许我没有得到正确的答案,所以有两个问题:

  1. 我可以在一次调用中执行多个语句Statement.execute()吗?
  2. 如果不是,那么使用 JDBC 运行具有多个语句的脚本的正确方法是什么(无需解析并将其拆分为单个语句)?
4

1 回答 1

0

老实说,如果这是一个 SQL 脚本,你最好对 psql 进行 shell 转义。这是处理这个问题的最好方法。一般来说,人们试图解析 SQL 代码并针对数据库运行它时,我遇到了太多令人不快的惊喜。如此疯狂的谎言。

您说“较小的脚本”,这使我得出结论,您正在做诸如设置数据库(或升级数据库,但由于没有查询而不太可能)之类的事情。通过 shell 转义使用 psql,不要回头。这确实是最好的方法。

我想如果你必须的话,你可以尝试在你的脚本中添加显式的 BEGIN 和 COMMIT 。

我不确定为什么它似乎隐含地提交了交易。您已正确设置自动提交。您的代码中没有明显的问题。您是否可能有旧的或有故障的 JDBC 驱动程序?如果没有,我建议使用 PostgreSQL JDBC 驱动程序项目提交错误报告。

于 2013-03-17T13:00:43.737 回答