无法提交JPA事务:事务标记为rollbackOnly

我在正在使用的其中一个应用程序中使用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()本身就是事务性的。不应该这样 这就是原因。

调用ServiceUser.method()方法时,会发生以下情况:

  1. 事务性拦截器拦截方法调用,并启动一个事务,因为没有事务已处于活动状态
  2. 该方法称为
  3. 该方法调用MyService.doSth()
  4. 事务拦截器拦截方法调用,发现事务已处于活动状态,并且不执行任何操作
  5. doSth()被执行并引发异常
  6. 事务拦截器拦截异常,将事务标记为rollbackOnly,并传播异常
  7. ServiceUser.method()捕获异常并返回
  8. 事务拦截器由于已经启动了事务,因此尝试提交它。但是Hibernate拒绝这样做,因为该事务被标记为rollbackOnly,因此Hibernate引发异常。事务拦截器通过引发包装hibernate异常的异常来将信号通知给调用方。

现在,如果ServiceUser.method()不是事务性的,将发生以下情况:

  1. 该方法称为
  2. 该方法调用MyService.doSth()
  3. 事务拦截器拦截方法调用,发现没有事务已处于活动状态,因此启动了一个事务
  4. doSth()被执行并引发异常
  5. 事务拦截器拦截异常。由于已启动事务,并且已引发异常,因此它将回滚事务并传播异常
  6. ServiceUser.method()捕获异常并返回

以上是 无法提交JPA事务:事务标记为rollbackOnly 的全部内容, 来源链接: utcz.com/qa/435235.html

回到顶部