Cor*_*rey 19 java spring hibernate transactions spring-mvc
引用Spring文档:
任何RuntimeException都会触发回滚,任何已检查的Exception都不会
未经检查的例外情况:
- 表示程序中的缺陷(错误) - 通常是传递给非私有方法的无效参数.引用来自Gosling,Arnold和Holmes的Java编程语言:"未经检查的运行时异常表示一般来说,它反映了程序逻辑中的错误,并且无法在运行时合理地恢复."
- 是RuntimeException的子类,通常使用IllegalArgumentException,NullPointerException或IllegalStateException实现
- 方法没有义务为其实现抛出的未经检查的异常建立策略(并且它们几乎总是不这样做)
检查异常:
- 代表程序直接控制范围之外的区域中的无效条件(无效的用户输入,数据库问题,网络中断,缺少文件)
- 是Exception的子类
- 方法有义务为其实现抛出的所有已检查异常建立策略(将已检查的异常传递到堆栈中,或以某种方式处理它)
如果在我的业务逻辑中我发现了一个问题并且我想要回滚更改,我必须抛出一个新的RuntimeException?它不是真正的RuntimeException(未经检查的异常),因为我已经在逻辑中识别出它.或许我误解了这些概念?
我真正的问题是,在我的@Transactional服务方法中回滚事务的最佳做法是什么?
Aff*_*ffe 12
如果您使用的是已检查的例外,则只需将它们添加到注释的rollbackFor
属性中即可@Transactional
.
@Transactional(rollbackFor = { MyInvalidUserException.class, MyApplicationException.class })
public void method() throws MyInvalidUserException, MyApplicationException {
...
...
}
Run Code Online (Sandbox Code Playgroud)
等等
org.life.java的答案也很好.如果您希望将程序化事务管理混合到声明性事务中或将其严格声明,则这是一个学术决策.
从内部以编程方式回滚:
@Transactional
public void commit() {
try {
// some business logic...
} catch (ConstraintViolationException e) {
// trigger rollback programmatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
Run Code Online (Sandbox Code Playgroud)
或标记回滚的异常并从调用者处理它:
@Transactional(rollBackFor = TransactionException.class)
public void commit() throws ConstraintViolationException{
try {
// some business logic...
} catch (ConstraintViolationException e) {
// handle the exception
// re-throw for rollback
new TransactionException(e);
}
}
public void doCommit(){
try {
commit()
} catch (TransactionException e){
// do nothing as already handled
}
}
Run Code Online (Sandbox Code Playgroud)
我更喜欢前者,因为它使代码更简单,但根据Spring文档,它是不鼓励的:
如果您绝对需要程序化回滚,则可以使用程序化回滚,但它的使用方式可以实现基于POJO的简洁体系结构.