我正在一个Java应用程序中工作,我需要同时执行这两个查询(如Java中的Strings),并在出现错误的地方回滚事务。

SELECT dblink_exec('hostaddr=xxx.xx.xxx.xxx port=5432 dbname=bdname user=myuser password=mypass connect_timeout=2',
'INSERT INTO table3(field4)
VALUES (5)') AS result;

SELECT dblink_exec('hostaddr=xxx.xx.xxx.xxx port=5432 dbname=bdname user=myuser password=mypass connect_timeout=2',
'UPDATE table1 SET field2 = field2 + 3.0 WHERE field1 = 16436') AS result;

更新

我创建了一个字符串,其中两个查询用;分隔,如注释建议中所示

更新

我已经尝试了JDBC原子事务作为Java中的代码。我强迫第二个sql失败,但是即使我指定.setAutoCommit(false); dblink通过第一个查询影响了另一个数据库。我在没有dblink事务的情况下尝试了相同的代码,并且回滚效果很好。 dblink是问题所在。

Java UPDATE
public static boolean ejecutarTransaccionDblink(String sql) {
    boolean estado = false;
    try {
        Statement sentencia = conexion.createStatement();
        conexion.setAutoCommit(false);
        if (sql.length() != 0) {
            if (sentencia.execute(sql)) {
                conexion.commit();
                estado = true;
            }
        }
    } catch (SQLException ex) {
        System.out.println(ex.toString());
        try {
            estado = false;
            conexion.rollback();
        } catch (SQLException ex1) {
        }
    } finally {
        try {
            conexion.setAutoCommit(true);
            return estado;
        } catch (SQLException ex) {
            return estado;
        }
    }
}

谢谢你的帮助。

最佳答案

为了在事务中运行查询,您只需要在连接上将auto-commit功能设置为false(记住在完成后将其设置回true,尤其是从连接池中检索连接时-因此重用)。

代码相对简单:

ResultSet resultado = null;
String statement1 = "SELECT dblink_exec('hostaddr=xxx.xx.xxx.xxx port=5432 dbname=bdname user=myuser password=mypass connect_timeout=2','INSERT INTO table3(field4) VALUES (5)') AS result";
String statement2 = "SELECT dblink_exec('hostaddr=xxx.xx.xxx.xxx port=5432 dbname=bdname user=myuser password=mypass connect_timeout=2','UPDATE table1 SET field2 = field2 + 3.0 WHERE field1 = 16436') AS result";
    try {
        // set auto-commit to false, to indicate start of transaction
        conexion.setAutoCommit(false);

        // run whatever queries you want on the connection, in a transaction, e.g. :
        Statement sentencia = conexion.createStatement();
        resultado = sentencia.executeQuery(sql);

        //manually commit the transaction when you're done
        conexion.commit();

        return resultado;
    } catch (SQLException ex) {
        System.out.println("Error Consulta:" + ex);

        // ensure transaction is rolled-back in case of error. (note: you might want to add an NPE check here
        con.rollback();
        return null;
    } finally {
        // close any statements / preparedStatements, etc. Note you MUST do this in the finally block, to ensure your connection won't stay in transaction.
        con.setAutoCommit(true);
    }

希望有帮助

更新

正如@a_horse_with_no_name指出的那样,dblink_exec连接到远程数据库,因此以上操作并不完整,因为它仅处理第一个数据库中的事务。

我相信答案应该在于使用名为的dblink_exec的连接,该过程涉及:
  • 使用dblink_connect打开新连接
  • 使用dblink_exec
  • 在新的命名连接中启动事务
  • 在先前打开的连接
  • 中使用dblink_exec执行查询1
  • 在先前打开的连接
  • 中使用dblink_exec执行查询2
  • 在先前打开的连接中提交事务

  • 因此,代码如下所示:
    SELECT dblink_connect('myconn','hostaddr=xxx.xx.xxx.xxx port=5432 dbname=bdname user=myuser password=mypass connect_timeout=2');
    SELECT dblink_exec('myconn','BEGIN');
    SELECT dblink_exec('myconn', 'INSERT INTO table3(field4) VALUES (5)');
    SELECT dblink_exec('myconn', 'UPDATE table1 SET field2 = field2 + 3.0 WHERE field1 = 16436');
    SELECT dblink_exec('myconn','COMMIT');
    

    事实是,这一切都未经测试,所以@KazMiller您可以尝试一下吗?

    09-27 18:12
    查看更多