在我们的应用程序中,我们使用Either
monad来传达失败。根据{{3}}文档,@Transactional
和DslContext.transaction
都需要抛出Exception
来触发事务回滚。我们更愿意根据Either的状态提交或回滚事务。
我们需要的Psuedo代码如下所示:
public class DomainService {
private DSLContext dslContext;
public Either<SomeError, String> businessOperation() {
return transactional(configuration ->
firstDatabaseChange(configuration)
.flatMap(i -> secondDatabaseChange(configuration)));
}
private Either<SomeError, String> firstDatabaseChange(
DSLContext dslContext) {
//Mutate the Db in some way
}
private Either<SomeError, String> secondDatabaseChange(
DSLContext dslContext) {
//Mutate the Db in some way
}
/* How do we implement this method */
private Either<SomeError, String> transactional(Function<DSLContext,
Either<SomeError, String>> function) {
return function.apply(dslContext)
.onSuccess(i -> /*Commit the transaction */)
.onFailure(i -> /*Rollback the transaction*/);
}
}
我有transactional
方法的以下工作实现,感觉就像一个黑客。 (有趣的是,即使我们没有抛出任何异常,回滚也需要@Transactional
注释才能工作。有更好的方法吗?
@Transactional
public <T> Either<SomeError, T> transactional(Function<DSLContext,
Either<SomeError, T>> function) {
Connection connection = dslContext.parsingConnection();
try {
connection.setAutoCommit(false);
Either<SomeError, T> either = function.apply(dslContext);
if (either.isSuccess()) {
connection.commit();
} else {
connection.rollback();
}
return result;
} catch (SQLException e) {
log.error("SqlException encountered", e);
return SomeError.failure(e);
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
log.error("Exception encountered while rolling back", e1);
}
return SomeError.failure(e);
}
}
答案 0 :(得分:1)
如Lukas Seder所述,程序API是关于Jooq的路线图:github.com/jOOQ/jOOQ/issues/5376
在此版本发布之前,您可以实现以下所需的行为:
public <T> Either<SomeError, T> transactional(Function<DSLContext,
Either<SomeError, T>> function) {
return dslContext.connectionResult(connection -> {
try {
connection.setAutoCommit(false);
Either<SomeError, T> either = function.apply(dslContext);
if (either.isSuccess()) {
connection.commit();
} else {
connection.rollback();
}
return result;
} catch (SQLException e) {
log.error("SqlException encountered", e);
return SomeError.failure(e);
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
log.error("Exception encountered while rolling back", e1);
}
return SomeError.failure(e);
}
});
}