我正在一个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
执行查询1dblink_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您可以尝试一下吗?