gpt4 book ai didi

java - 如何避免捕获 EJB Rollbacked ApplicationException 后回滚?

转载 作者:行者123 更新时间:2023-12-01 11:51:49 25 4
gpt4 key购买 nike

我们面临类似于以下的场景:

@ApplicationException(rollback = true)
class UniqueConstraintViolated extends RuntimeException { ... }

interface GenericStorageService {
void insert(Object ety); // throws UniqueConstraintViolation
}

class ServiceA {
@Inject GenericStorageService store;

void insert(A ety) {
someSideEffect();
store.insert(ety);
someOtherSideEffect();
}
}

class ServiceB {
@Inject GenericStorageService store;

void insertIfNotYetPresent(B ety) {
try {
someSideEffect();
store.insert(ety);
someOtherSideEffect();
} catch (UniqueConstraintViolation e) {
// that's totally ok
}
}
}

在这种情况下,

  • 请求插入之前插入的某个 A 是一个实际的用户错误。事务无法以有意义的方式提交。
  • 请求插入一些先前存在的B不是错误。只需确认所述B的存在即可安全地提交事务。特别是,无论之前是否插入了给定的 B,都需要提交副作用。

根据(我对)EJB 规范的理解,上述代码在任何一种情况下都会触发回滚,而不会导致所需的语义。

据我了解,EJB 给我们留下了以下选择:

  1. 使用 rollback = false 装饰 UniqueConstraintViolated,在 ServiceA 中手动捕获它,并通过编程事务控制回滚事务。
  2. UniqueConstraintViolated 拆分为两个同级 UniqueConstraintViolatedThatNeedsRollbackUniqueConstraintViolatedThatNeedsNoRollback。此外,用两个变体 insertWithRollbackingUniqueConstraintinsertWithNonRollbackingUniqueConstraint 替换 GenericStorageServiceinsert 方法。
  3. 只是吸它。

选项 1 是不可取的,因为大多数服务与 ServiceA 的类型相同,因此 rollback = true 是更准确的选择。此外,它还破坏了声明式事务控制的优雅性。

选项 2 是不可取的,因为对于 GenericStorageService 来说,这两种情况实际上是相同的。在这个层面上进行区分是没有意义的。此外,UniqueConstraintViolated 并不是唯一需要区分的异常(exception)......我们会遭受组合爆炸。

选项 3 无需进一步解释。

这给我留下了最后一个问题:

选项 4 是什么?

最佳答案

对于选项2,这通常是我的解决方法。

//So generic transaction service, that commits every transaction in a different transaction context.
@Stateless
@TransactionAttribute(REQUIRES_NEW)
public class TransactionalService {

public void executeTransactional(final Runnable task) {
task.run();
}
}

@Statless
public class ServiceB {

@Inject GenericStorageService store;
@Inject TransactionalService transactionalService;

public void insertIfNotYetPresent(B ety) {
try {
transactionalService.executeTransactional(new Runnable() {
public void run() {
store.insert(ety);
}
};

transactionalService.executeTransactional(new Runnable() {
public void run() {
someSideEffect();
}
};

} catch (UniqueConstraintViolation e) {
// that's totally ok
}
}
}

//如果你使用的是java 8,非常简单,所有的冗长都消失了

@Statless
public class ServiceB {

@Inject GenericStorageService store;
@Inject TransactionalService transactionalService;

public void insertIfNotYetPresent(B ety) {
try {
transactionalService.executeTransactional(() -> store.insert(ety) );
transactionalService.executeTransactional(() -> someSideEffect() );

} catch (UniqueConstraintViolation e) {
// that's totally ok
}
}
}

关于java - 如何避免捕获 EJB Rollbacked ApplicationException 后回滚?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28750367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com