use*_*601 39 java spring hibernate jpa
我正在使用Spring和Hibernate在我正在处理的一个应用程序中,我遇到了处理事务的问题.
我有一个加载一些实体从数据库中的服务类,修改了一些它们的值,然后(当一切都有效)提交这些更改到数据库.如果新值无效(我只能在设置后检查),我不想保留更改.为了防止Spring/Hibernate保存更改,我在方法中抛出异常.但是会导致以下错误:
Could not commit JPA transaction: Transaction marked as rollbackOnly
Run Code Online (Sandbox Code Playgroud)
这是服务:
@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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我调用它的方式:
class ServiceUser {
@Autowired
private MyService myService;
public void method() {
try {
myService.doSth();
} catch (MyCustomException e) {
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
我期望发生的事情:没有对数据库的更改,也没有对用户可见的异常.
会发生什么:没有更改数据库但应用程序崩溃:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction;
nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
Run Code Online (Sandbox Code Playgroud)
它正确地将事务设置为rollbackOnly,但为什么回滚会因异常而崩溃?
JB *_*zet 58
我的猜测是,这ServiceUser.method()本身就是交易性的.它不应该.这就是原因所在.
以下是调用ServiceUser.method()方法时发生的情况:
现在,如果ServiceUser.method()不是事务性的,那么会发生什么:
Yar*_*hiy 20
无法提交JPA事务:事务标记为rollbackOnly
当您调用也标记为的嵌套方法/服务时,会发生此异常@Transactional.JB Nizet详细解释了这种机制.我想在它发生时添加一些场景以及一些避免它的方法.
假设我们有两个Spring服务:Service1和Service2.从我们的计划,我们称之为Service1.method1()进而调用Service2.method2():
class Service1 {
@Transactional
public void method1() {
try {
...
service2.method2();
...
} catch (Exception e) {
...
}
}
}
class Service2 {
@Transactional
public void method2() {
...
throw new SomeException();
...
}
}
Run Code Online (Sandbox Code Playgroud)
SomeException 取消选中(扩展RuntimeException),除非另有说明.
场景:
标记为由异常抛出的回滚标记的事务method2.这是JB Nizet解释的默认情况.
注释method2作为@Transactional(readOnly = true)仍然标志着回滚事务(从退出时抛出的异常method1).
注释都method1与method2作为@Transactional(readOnly = true)仍然标志着回滚事务(从退出时抛出的异常method1).
注释method2用于@Transactional(noRollbackFor = SomeException)防止标记事务以进行回滚(退出时不会抛出异常method1).
假设method2属于Service1.调用它method1不会通过Spring的代理,即Spring不知道SomeException被抛出method2.在这种情况下,事务未标记为回滚.
假设method2没有注释@Transactional.调用它method1确实通过Spring的代理,但Spring不关注抛出的异常.在这种情况下,事务未标记为回滚.
注解method2与@Transactional(propagation = Propagation.REQUIRES_NEW)品牌method2启动新的事务.第二个事务在退出时标记为回滚,method2但在这种情况下原始事务不受影响(退出时不会抛出异常method1).
如果SomeException被选中(不继承RuntimeException),Spring缺省不适用于回滚事务标记时拦截检查的异常(也不例外,从退出时抛出method1).
查看此要点中测试的所有方案.
| 归档时间: |
|
| 查看次数: |
98621 次 |
| 最近记录: |