我有一个@Transactional标记的类FooServiceImpl,需要用从另一个@Transactional类BarServiceImpl获得的值填充一个对象FooDetails。
尝试从BarServiceImpl获取值时,会抛出Exception1。我想将FooDetails字段保留为空,该字段的setter抛出异常并捕获异常。即使某些setter抛出异常,所有其他字段也必须保持填充状态。
可悲的是,情况并非如此,因为事务已被标记为仅回滚,因为抛出了Exception1,尽管我明确地将该方法标记为“noRollbackFor=Exception1.class”并捕获了异常。
为什么会发生这种情况,我如何修复代码以填充设置器没有抛出异常的所有字段,并将设置器抛出异常的字段留空。这是导致行为的代码:
@Service
@Transactional
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionalService {
// The name of the service
String value() default "";
}
public class FooDetails {
private String fieldA;
private String fieldB;
// getters and setters
...
}
@TransactionalService
public class BarServiceImpl implements BarService {
@Override
public String getFieldB() throws Exception1 {
...
try {
...
} catch (Exception2 e2) {
...
throw new Exception1();
} catch (Exception3 e3) {
...
throw new Exception1();
}
}
}
@TransactionalService
public class FooServiceImpl implements FooService {
...
...
@Autowired BarService barService;
@Override
@Transactional(noRollbackFor = {Exception1.class, Exception2.class, Exception3.class})
public FooDetails getFooDetails(Long fooId) {
Foo foo = fooDao.get(fooId);
if (foo == null) {
return null;
}
FooDetails fooDetails = new FooDetails();
// getAFooDetails() has no exceptions to throw => ok
fooDetails.setFieldA(getAFooDetails());
// barService.getFieldB() throws an Exception1 => results in
// "org.springframework.transaction.UnexpectedRollbackException:
// Transaction rolled back because it has been marked as rollback-only" => all foo fields left empty
try {
fooDetails.setFieldB(barService.getFieldB());
} catch (Exception1 e) {
LOG.info(e.getMessage());
}
}
}
您正在使用两个逻辑事务作用域:外部事务作用域(在FooServiceImpl中)和内部事务作用域(在BarServiceImpl中)。两者都属于同一个物理事务。
因为您说Exception1是一个已检查的异常,所以在BarServiceImpl中抛出它不会导致任何回滚(直到显式声明)。在FooServiceImpl中捕获它也不会导致任何回滚。
通常,如果内部事务范围(此处:您的BarServiceImpl.getFieldB)触发回滚,则会抛出一个UnoutedRollbackException。当外部事务范围的调用方法(此处:您的FooServiceImpl.getFoo细节)正常返回时,Spring的AbstractPlatformTransactionManager将尝试提交。此提交失败,因为其他人已经将其标记为“rollbackOnly”(由内部事务范围完成)。然后它会将一个UnoutedRollbackException抛回给FooServiceImpl.getFoo细节的调用者。
所以,你的BarServiceImpl。getFieldB一定以某种方式引发了未经检查的异常(与异常1不同)
或
您在此处未显示的代码中的其他地方使用了一个单一的物理事务,并且这段代码确实通过未经检查的异常触发了回滚。
问题内容: 我有这样的方法: 我想抛出一个内。编译器不允许我这样做,因为不允许将我的方法扔在那里。但是我需要抛出一个的子类来进行测试 (我不能抛出Unchecked)。显然这是一个hack,但我需要进行测试。我尝试过EasyMock,但它也不允许我这样做。任何想法如何做到这一点? 谢谢,肖恩·阮 问题答案: 方法1: Alexey Ragozin的这篇文章介绍了如何使用泛型技巧引发未声明的检查异常
抛出异常有什么意义?例如,我偶然发现: 但是当你不扔零点的时候,你也会得到一个零点?我经常看到这个,我想知道这是否是一个学习的好习惯?
当我从EJB调用一个方法时,我遇到了一个奇怪的异常。EJB的方法只是参考BD并返回一个VO。当我从一个独立的客户机调用该方法时,所有这些都能很好地工作,但是当我从同一台服务器、从另一个EJB调用该方法时,它返回:org。天啊。科尔巴。未知:重新引发挂起的异常时发现意外异常:(.VOObject)vmcid:IBM次要代码:EA5已完成:可能 服务器是WebSphereApplicationServ
问题内容: 我试图在Netbeans中重构一个大型程序,但我有点迷茫。我从来没有非常模块化,但是现在通过实际学习如何做到这一点来尝试纠正这种情况,并在将来纠正这种情况。不幸的是,我在将某些教程翻译成我的程序时遇到了麻烦。所以我希望这里有人可以帮忙。目前,我正在尝试分解一部分采用特定格式的文件并制成表格的代码。我知道我需要创建一个类并使用它来创建表对象,但是我不确定如何做。我有一个主文件,用于获取文
我有一个Spring/JPA配置,其中Hibernate作为持久性提供者。但是,我不明白为什么在没有打开事务的情况下对以下DAO代码调用save()时没有抛出TransactionRequiredException(DAO/服务中没有@Transactional): 正如预期的那样,实体没有保存,但为什么没有引发异常?持久化的javadoc表示,持久化()应该抛出一个“Transaction必需的
我想问一下这种行为的原因,因为在运行Spring方法/类时,我似乎不完全理解Hibernate中的和之间的区别。 下面的代码应该回滚DB操作,但它没有回滚(整个类注释为): 以下代码在引发异常时按预期回滚: save()方法来自类,因此它的代码是: 该实体是一个已存在的实体,因此我理解它正在执行。根据JPA规范: find方法(前提是在没有锁的情况下调用它或使用LockModeType.None调