【发布时间】:2018-11-17 01:00:22
【问题描述】:
在我们的应用程序中,我们使用 Either monad 来传达故障。根据Jooq transaction management 文档,@Transactional 和DslContext.transaction 都需要抛出Exception 来触发事务回滚。我们更愿意根据 Either 的状态提交或回滚事务。
我们需要的伪代码如下所示:
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);
}
}
【问题讨论】:
-
我不确定你为什么认为你的实现是一个 hack。你只需要自己做。您不妨从问题中删除实现,并将其作为您自己问题的答案。
-
@LukasEder 感谢您的快速回复。我希望 Jooq 中有另一个 API(我没有注意到)可以让我在不下降到
Connection级别的情况下实现这一目标。另外,我担心直接使用parsingConnection的影响。你知道为什么仍然需要@Transactional才能让它工作吗? -
路线图上有一个替代的程序 API:github.com/jOOQ/jOOQ/issues/5376。不知道
parsingConnection是怎么关联的,这里为什么会涉及@Transactional。我想你的问题并不完整,关于后者...... -
parsingConnection被标记为实验性功能。因此,我想知道它在用于事务管理时是否会出现任何问题。从您链接的问题中,我看到我可以使用dslContext.connectionResult来实现相同的结果@Transactional理想情况下不应该存在,但我们发现connection.rollback()在缺少注释时似乎实际上没有做任何事情.但是,这可能与我们的应用程序的设置方式非常具体。 -
哦,您刚刚尝试从 jOOQ 获取 any JDBC
Connection?是的,DSLContext.connection()或connectionResult()是要走的路。不要使用parsingConnection()。 Javadoc 非常清楚它的用途 :)
标签: transactions jooq