以下是一个示例代码:
try ( PgConnection conn = application.adminDb.getConnection() ) {
// execute SQL statements here (and other possible statements)
}
我希望AutoCloseable PgConnection类在创建时开始新事务,并在关闭时启动COMMIT或ROLLBACK。如果try块中没有抛出异常,它应该是COMMIT,否则它应该是ROLLBACK。
我真正需要的是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;
}
}
但是我需要这样做一百次,所以我正在寻找一种选择,即“吵闹”#34;
更新
我当然可以这样做:
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 :只是为了澄清问题:我不想压制或转换例外。我只想在没有异常时提交,并在有异常时回滚。但除此之外,我不想从内部处理它们 - 它们应该传播给调用者,不会改变。
答案 0 :(得分:-1)
以下是我对扩展代码的想法。你怎么看?至少你不必捕获异常并在整个地方处理它们以提交/回滚你的事务
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
}
});
}
}
}