java - PostgreSQL 事务失败 : "there is no transaction in progress"

标签 java postgresql jdbc transactions

我尝试使用 JDBC for PostgreSQL 执行一个相当长的事务。在 JDBC 中,我不能使用 COMMITROLLBACK,所以我试图在 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 警告,我可以看到数据库实际上正在处理我发送的整个脚本,就在提交,这一切都失败了。

顺便说一句,交易完全没问题。我将它的精确副本写入一个文件,然后通过将它复制到 pgAdmin 中,我可以毫无错误地运行它。希望你能在这方面帮助我,我已经搜索和测试了好几个小时......

编辑

可能我没听懂,所以有两个问题:

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

最佳答案

老实说,如果这是一个 SQL 脚本,你最好做一个 shell 转义到 psql。这是处理这件事的最好方法。总的来说,我从试图解析 SQL 代码并针对数据库运行它的人那里得到了太多不愉快的惊喜。疯狂就是这样撒谎的。

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

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

我不确定为什么它似乎在隐式提交事务。您已正确设置自动提交。您的代码中没有明显的问题。您是否有一个旧的或有问题的 JDBC 驱动程序?如果没有,我会建议使用 PostgreSQL JDBC 驱动程序项目提交错误报告。

关于java - PostgreSQL 事务失败 : "there is no transaction in progress",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15275532/

相关文章:

java - 从 Fragment 启动 Activity 抛出 ClassNotFoundException

java - Android X : tools:replace specified at line: for attribute, 但未指定新值

sql - 已授予所有锁的 postgresql "idle in transaction"

java - 从eclipse导入项目到intellij : error with JDBC mysql

java - 如何从 mysql 表中获取最后 3 个不同的 ID

java - jaxb base64二进制编码/解码

java - 简单的套接字程序

postgresql 服务器不听

Postgresql COPY 命令 - 如何删除临时文件?

mysql - 错误代码 1064,SQL 状态 42000 : You have an error in your SQL syntax;