这是一个示例代码:
try ( PgConnection conn = application.adminDb.getConnection() ) {
// execute SQL statements here (and other possible statements)
}
我希望AutoCloseable PgConnection类在创建时开始新事务,并在关闭时启动COMMIT或ROLLBACK。如果try块中没有抛出异常,它应该是COMMIT,否则它应该是ROLLBACK。
我真正需要的是一个上下文管理器a'la Python。有可能以某种方式这样做吗?理论上,在调用PgConnection.close()时,JVM已经知道是否存在异常。只是不知道该怎么说。
当然,我可以这样明确:
try ( PgConnection conn = application.adminDb.getConnection()) {
conn.begin();
try {
// execute SQL statements here
conn.commit();
} catch (Exception e) {
conn.rollback();
throw e;
}
}
但我需要这样做一百次,所以我正在寻找一个“减少噪音”的选项。
UPDATE
我当然可以这样做:
public interface PgTransactionWrapper {
public void run(PgConnection connection) throws SQLException;
}
然后把它放到PgConnection中:
public void runInTransaction(PgTransactionWrapper wrapper) throws SQLException {
int trId = begin();
try {
wrapper.run(this);
commit(trId);
} catch (SQLException e) {
rollback(trId);
throw e;
}
}
这是如何使用它:
try ( PgConnection conn = application.adminDb.getConnection() ) {
conn.runInTransaction(new PgTransactionWrapper() {
@Override
public void run(PgConnection connection) throws SQLException {
// SQL statements here
}
});
}
但我认为情况更糟。确实实现了自动提交/回滚,但要付出的代价是更多的语法噪音,并引入了一个额外的问题:事务包装器不能抛出除SQLException之外的任何东西。
我想念的是AutoCloseable.close(Exception excOrNull)的一个简单参数,但我想这是语言的限制,而且无法完成。 :-(
更新2:只是澄清一个问题:我不想压制或转换异常。我只想在没有异常时提交,并在有异常时回滚。但除此之外,我不想从内部处理它们 - 它们应该传播给调用者,不加改变。
以下是我对扩展代码的想法。你怎么看?至少您不必捕获异常并在整个地方处理它们以提交/回滚您的事务
public interface SQLStatementExecutor { void run(PgConnection connection) throws SQLException; } public class PgConnectionWrapper implements Closeable { private PgConnection connection; private boolean status = false; public PgConnectionWrapper() { connection = obtainConnection(); } private PgConnection obtainConnection() { return application.adminDb.getConnection(); } public void runInTransaction(SQLStatementExecutor executor) throws SQLException { try { executor.run(connection); status = true; } catch (SQLException e) { status = false; throw e; } } public PgConnection getConnection() { return connection; } @Override public void close() throws IOException { if (status) { connection.commit(); } else { connection.rollback(); } connection.close(); } } public class TestMain { public static void main(String[] args) throws IOException { try (PgConnectionWrapper connectionWrapper = new PgConnectionWrapper()) { connectionWrapper.runInTransaction(new SQLStatementExecutor() { @Override public void run(PgConnection connection) throws SQLException { // SQL statements, but no commit or rollback } }); } } }