Spring @Transactional 方法错误处理
Spring @Transactional method Error handling
我正在使用使用 @Transactional
注释的事务方法。我正在尝试使用 JpaRepository 的 save() 方法将一个对象保存到数据库中。 (由于对数据库关系的约束,这将引发错误。)
现在,当我调试程序时,我发现在事务方法结束时抛出异常,而不是在调用 save
方法时抛出异常。这与非事务方法的行为截然不同。
有人可以解释为什么会这样吗?为什么在事务方法结束时抛出异常,而不是在实际应该发生的时候抛出。
我的第二个问题是,当方法是事务性时,抛出的异常是DataViolationException
,当它是非事务性时,抛出的异常是PSQLException
(使用Postgres数据库)。为什么?
下面是代码
@Transactional
public ResponseType methodA(UserObject userObject) {
//save call
jpaRepoObject.save(userObject);
//next call will fail due to relational constraints on database
jpaRepoObject.save(userObject); //should throw PSQLException/DataViolationException
return new ResponseType("success"); //Error thrown after this line.
}
save
不会立即将数据刷新到基础数据库。首先,实体被保存到一级缓存中,并且,当刷新时间到来时(在事务结束时 - 就像你的情况,或者发出查询时),只有实体被保存到数据库中。
要查看您期望的行为,请使用 saveAndFlush
方法。
这是 JPA 的一项功能,称为事务性后写。您的代码正在执行的所有插入和更新都由 Jpa 实现存储,直到事务被刷新。这让 jpa 实现重新排序这些操作,以最合理的顺序进行。
刷新意味着执行到目前为止由entityManager 实例存储的所有操作。您可以告诉 entityManager 刷新,或者一旦达到事务边界它就会自动刷新。
显式刷新的一个例子是,如果您正在插入一个实体,并且您需要为它生成一个 ID,以便稍后可以在相同的方法中使用它。
您始终可以在事务中 运行 sql 并稍后提交或回滚。刷新 运行s sql 但不提交。
我正在使用使用 @Transactional
注释的事务方法。我正在尝试使用 JpaRepository 的 save() 方法将一个对象保存到数据库中。 (由于对数据库关系的约束,这将引发错误。)
现在,当我调试程序时,我发现在事务方法结束时抛出异常,而不是在调用 save
方法时抛出异常。这与非事务方法的行为截然不同。
有人可以解释为什么会这样吗?为什么在事务方法结束时抛出异常,而不是在实际应该发生的时候抛出。
我的第二个问题是,当方法是事务性时,抛出的异常是DataViolationException
,当它是非事务性时,抛出的异常是PSQLException
(使用Postgres数据库)。为什么?
下面是代码
@Transactional
public ResponseType methodA(UserObject userObject) {
//save call
jpaRepoObject.save(userObject);
//next call will fail due to relational constraints on database
jpaRepoObject.save(userObject); //should throw PSQLException/DataViolationException
return new ResponseType("success"); //Error thrown after this line.
}
save
不会立即将数据刷新到基础数据库。首先,实体被保存到一级缓存中,并且,当刷新时间到来时(在事务结束时 - 就像你的情况,或者发出查询时),只有实体被保存到数据库中。
要查看您期望的行为,请使用 saveAndFlush
方法。
这是 JPA 的一项功能,称为事务性后写。您的代码正在执行的所有插入和更新都由 Jpa 实现存储,直到事务被刷新。这让 jpa 实现重新排序这些操作,以最合理的顺序进行。
刷新意味着执行到目前为止由entityManager 实例存储的所有操作。您可以告诉 entityManager 刷新,或者一旦达到事务边界它就会自动刷新。
显式刷新的一个例子是,如果您正在插入一个实体,并且您需要为它生成一个 ID,以便稍后可以在相同的方法中使用它。
您始终可以在事务中 运行 sql 并稍后提交或回滚。刷新 运行s sql 但不提交。