如何从事务性Spring服务中抛出自定义异常?


问题内容

我有这个spring服务:

@Service
@Transactional
public class ConsorcioServiceImpl implements ConsorcioService {

    ...

    @Autowired
    private ConsorcioRepository consorcioRepository;

    @Override
    public void saveBank(Consorcio consorcio) throws BusinessException {

        try {
            consorcioRepository.save(consorcio);
        }
        catch(DataIntegrityViolationException divex) {
            if(divex.getMessage().contains("uq_codigo")) {
                throw new DuplicatedCodeException(divex);
            }
            else {
                throw new BusinessException(dives); 
            }
        }
        catch (Exception e) {
            throw new BusinessException(e);
        }
    }


}

该服务使用以下Spring Data存储库:

@Repository
public interface ConsorcioRepository extendsCrudRepository<Consorcio, Integer> {


}

我从Spring控制器调用服务:

@Controller
@RequestMapping(value = "/bank")
public class BancaController {

    @Autowired
    private ConsorcioService consorcioService;

    @RequestMapping(value="create", method=RequestMethod.POST)
    public ModelAndView crearBanca(@Valid BancaViewModel bancaViewModel, BindingResult bindingResult,
                                   RedirectAttributes redirectAttributes) {
        ModelAndView modelAndView;

        MessageViewModel result;
        try {

            consorcioService.saveBank(bancaViewModel.buildBanca());
            result = new MessageViewModel(MessageType.SUCESS);
            redirectAttributes.addFlashAttribute("messageViewModel", result);
            modelAndView = new ModelAndView("redirect:/banca/crear");
            return modelAndView;
        } catch (Exception e) {
            result = new MessageViewModel(MessageType.ERROR);
            modelAndView = new ModelAndView("crear-bancas");
            modelAndView.addObject("messageViewModel", result);
            return modelAndView;
        }
}

但是我在控制器中得到的例外是:org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
而不是DuplicatedCodeException我抛出了服务。我需要确定异常的类型,以便提供自定义友好的用户消息。


问题答案:

同样,您的DuplicatedCodeException,BusinessException应该是运行时异常,或者为方法saveBank添加:

@Transactinal(rolbackFor =
{BusinessException.class,DuplicatedCodeException。,class})

在其他情况下,spring不会回滚事务。

从Spring文档:

尽管EJB的默认行为是使EJB容器在系统异常(通常是运行时异常)时自动回滚事务,但是EJB
CMT不会在应用程序异常(即Java以外的已检查异常)时自动回滚事务。
.rmi.RemoteException)。尽管Spring声明式事务管理的默认行为遵循EJB约定(仅针对未检查的异常会自动回滚),但是自定义它通常很有用。