2017-06-15 7 views
1

私はこの春のサービスがあります。トランザクション型Springサービスからカスタム例外をスローするにはどうすればいいですか?

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


} 

私は春のコントローラからサービスを呼んでいる:

@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; 
     } 
} 

しかし、サービスは、この春データリポジトリを使用していること

@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); 
     } 
    } 


} 

私がコントローラに入る例外は、DuplicatedCodeExceptionの代わりにorg.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly です。私は例外の種類を特定する必要があるので、私はカスタムフレンドリーなユーザーメッセージを与えることができます。

答えて

0

あなたDuplicatedCodeException、BusinessExceptionは、ランタイム例外、または方法saveBankために追加する必要があります

@Transactinal(rolbackFor = {。BusinessException.class、DuplicatedCodeException、クラス})

春の場合はトランザクションをロールバックしません。春のドキュメントから

にEJBコンテナが自動的にシステム例外でトランザクションをロールバックするためにEJBのデフォルトの動作ですが(通常 実行時例外)、EJB CMTはロールバックしません。トランザクション がアプリケーション例外(つまり、チェックされた 例外、java.rmi.RemoteException以外)で自動的に発生します。 Spring 宣言的トランザクション管理のデフォルトの動作は、EJB の規則に従いますが(ロールバックはチェックされていない例外の場合にのみ自動です)、 はこれをカスタマイズすると便利なことがよくあります。

+0

は、私が代わりにException' 'のRuntimeException''から継承や行動がIようでした期待される。 –

1

catch (Exception e)より前にcatch (TransactionSystemException tse)を追加し、getOriginalException()で例外を抽出してください。

try { 
    consorcioService.saveBank(bancaViewModel.buildBanca()); 
    result = new MessageViewModel(MessageType.SUCESS); 
    redirectAttributes.addFlashAttribute("messageViewModel", result); 
    modelAndView = new ModelAndView("redirect:/banca/crear"); 
    return modelAndView; 
} catch (TransactionSystemException tse) { 
    final Throwable ex = tse.getOriginalException(); 
    if (ex instanceof DuplicatedCodeException) { 
     // DuplicatedCodeException 
    } 
} catch (Exception e) { 
    result = new MessageViewModel(MessageType.ERROR); 
    modelAndView = new ModelAndView("crear-bancas"); 
    modelAndView.addObject("messageViewModel", result); 
    return modelAndView; 
} 
0

あなたの例外はRollbackExceptionで包まれているため、その原因はThrowableです。それはのターンでもTransactionSystemExceptionの原因です。

あなたが望むようにすべての例外をキャッチし、カスタマイズするためにグローバルな例外ハンドラを構築することができます。

@ControllerAdvice 
class GlobalControllerExceptionHandler { 
    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler(TransactionSystemException.class) 
    public ModelAndView handleDupilatedCode(HttpServletRequest req, TransactionSystemException ex) { 
     // Build you exception body here 
     Throwable e = ex.getOriginalException(); 
     if(e instanceof DuplicatedCodeException) 
      // throw 
     // Or build custom exception as you want 
     ModelAndView mav = new ModelAndView(); 
     mav.addObject("exception", e); 
     mav.addObject("url", req.getRequestURL()); 
     mav.setViewName("error"); 
     return mav; 
    } 
} 

@ControllerAdviceはまた、あなたが@Controllerレベルで@ExceptionHandlerを使用し、またはこれを作成することができます春3.2

以降で使用可能ですすべてのコントローラのスーパークラスとして1つがある場合、抽象コントローラで処理します。

public class FooController { 

    //... 
    @ExceptionHandler({ CustomException1.class, CustomException2.class }) 
    public void handleException() { 
     // 
    } 
} 

他のいくつかのアプローチがありますが、完全な参照のために従ってください。

Spring IO: Exception handling in Spring MVC

Baeldung: Exception handling with Spring

関連する問題