【发布时间】:2014-10-08 23:12:44
【问题描述】:
我在我正在处理的一个应用程序中使用 Spring 和 Hibernate,但在处理事务时遇到了问题。
我有一个服务类,它从数据库加载一些实体,修改它们的一些值,然后(当一切都有效时)将这些更改提交到数据库。如果新值无效(我只能在设置后检查)我不想保留更改。为了防止 Spring/Hibernate 保存更改,我在方法中抛出了异常。然而,这会导致以下错误:
Could not commit JPA transaction: Transaction marked as rollbackOnly
这就是服务:
@Service
class MyService {
@Transactional(rollbackFor = MyCustomException.class)
public void doSth() throws MyCustomException {
//load entities from database
//modify some of their values
//check if they are valid
if(invalid) { //if they arent valid, throw an exception
throw new MyCustomException();
}
}
}
这就是我调用它的方式:
class ServiceUser {
@Autowired
private MyService myService;
public void method() {
try {
myService.doSth();
} catch (MyCustomException e) {
// ...
}
}
}
我期望发生的事情:数据库没有变化,用户也看不到异常。
会发生什么:数据库没有更改,但应用程序崩溃:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction;
nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
它正确地将事务设置为rollbackOnly,但是为什么回滚会因异常而崩溃?
【问题讨论】:
-
我的猜测是 ServiceUser.method() 本身就是事务性的。不应该。发布完整的堆栈跟踪。
-
尝试在
@Transactional注解中使用noRollbackFor而不是rollbackFor -
@JBNizet 哇,好猜,在 ServiceUser 的类声明中实际上有一个
@Transactional注释。删除它后,它可以完美运行。您能否发表您的评论作为答案(或许可以简要解释一下为什么它不应该是事务性的)?