我使用 @Transactional
注释来进行回滚,我在 Spring-Boot 应用程序中添加了 Controller 方法,因此只有在一切都发生且没有任何错误的情况下才会进行保存,这就是我添加注释的方式:
@PostMapping(value = "/add/people")
@Transactional
public ResponseEntity<?> addGroundToPerson(@RequestParam("ground") String newGround, @RequestParam("person") String person {
try {
personService.addPerson(person, ground);
Ground addedGround = groundService.addGround(pnewGround);
} catch (NoSuchElementException e) {
return new ResponseEntity<>(new CustomErrorType(e.getMessage()), HttpStatus.NOT_IMPLEMENTED);
}
addPersonToGround 正在将该人及其地址保存到数据库中。
addGround 正在使用该人的引用将新地面保存在数据库中,并且地面本身有一个地址。
我的服务方法失败:
public void registerAddress(HasAddress hasAddress) throws NoSuchElementException {
Address address = hasAddress.getAddress());
State state = address.getState();
//here's where I'm getting the error
State dbState = searchState(state); //stateRepository.getStateByName();
address.setState(state);
hasAddress.setAddress(address);
addressRepository.save(address);
}
RegisterAddress 被调用了两次,第一次工作正常,但因为我第一次保存了,所以第二次不起作用。 (请记住,我的代码比这个大得多,我不能直接取消保存,我已经尝试过了,相信我)。
我尝试将 @Transactional 放入服务层,但它向我发送了此错误:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance
当我只保存对象时,它工作正常,但当我必须在保存后获取对象时,它工作正常。这就是我的问题,我最好的例子是这样的:
- 每个人都有一个地址,其中包含州/省/自治区。
- 如果每个地址的状态相同,我想重复使用该状态。
- 我注册一个人,它注册一个新地址(有时使用数据库中已存在的状态)。
- 我尝试注册地面,当我尝试让该状态重用它时,出现错误:
nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit
我认为发生这种情况是因为当我第一次“保存”对象时它不会提交,因此它保持 transient ,而我只是无法获取 transient 对象。我试图制作所有逻辑并在其末尾保存,或者如果发生一些异常则回滚,但由于注释,我收到了该错误。
最佳答案
这件事有很多问题。首先,您已将 @Transactional
放入 Controller 层而不是服务层。您的方法的逻辑也应该位于服务层。这个 - rollbackFor = Exception.class
并不是真正必要的,因为 Spring 默认在所有用 注释的方法上放置
。现在您收到上述异常的原因是因为您在其中放置了一个 try/catch block 。仅当抛出异常时,Spring 的事务才会被标记为回滚,无论异常是否被捕获。您必须删除 try/catch 或找到一种在事务之外执行此操作的方法。rollbackFor = { RuntimeException.class, Error.class }
@事务性
关于java - 如何使用@Transactional读取spring方法中保存的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60514027/