データベースを使用して入力値をチェックする
データベースの状態を用いた入力値のチェックをしたい場合、バリデーションを実装する必要があります。
Tip
例えばバリデーションで重複登録のチェックを行ったとしても、同時に複数の登録処理が行われてしまうとバリデーションのタイミングでエラーにならないというようなこともありえます。バリデーションだけでデータの不整合を確実に防げるわけではありませんので、データベースの制約を使用する等、データの不整合が発生しないよう十分に注意してください。
以下のサンプルコードの動作確認環境については、 動作確認環境と依存ライブラリについて を参照してください。
実装例
Serviceで送出した例外をControllerで捕捉し、画面にエラーメッセージを表示します。
- Controller
@PostMapping("/") public ModelAndView add(@Valid @ModelAttribute Form form, BindingResult bindingResult, RedirectAttributes redirectAttributes) { if (bindingResult.hasErrors()) { return createValidationErrorResponse(); } try { userService.insert(new User(form.getName(), form.getMailAddress().getValue(), form.getRole())); } catch (UserService.RoleNotFoundException e) { // ロールがデータベースのロールテーブル上に存在しない例外を捕捉して // 画面にメッセージを表示します。 bindingResult.rejectValue("role", "role.notFound"); return createValidationErrorResponse(); } catch (DuplicateKeyException e) { // 同じメールアドレスがデータベースに登録済みの場合には // 重複エラーが送出されるのでそれを元に画面にメッセージを表示します。 bindingResult.rejectValue("mailAddress", "mailAddress.duplicated"); return createValidationErrorResponse(); } // message-source-start // MessageSourceから完了メッセージを取得して、Flashスコープに設定します。 // プレースホルダに、「ユーザ」を設定します。 redirectAttributes.addFlashAttribute("successMessage", messageSource.getMessage("add.success", new String[]{"ユーザ"}, LocaleContextHolder.getLocale())); // message-source-end return new ModelAndView("redirect:/"); } private ModelAndView createValidationErrorResponse() { return new ModelAndView("index", HttpStatus.BAD_REQUEST); }
- Service
@Transactional public void insert(User user) { // ロールの存在チェック // 本来は外部キーの制約違反でハンドリングすべきですが、 // ここでは実装例を示すためこのような実装にしています。 if (!roleDao.existsRole(user.role)) { throw new RoleNotFoundException(); } userDao.insert(user); }
- メッセージ定義(messages.properties)
typeMismatch.java.lang.Integer=数値で入力してください。 typeMismatch.keel.validation.value.MailAddress=メールアドレス形式(sample@example.com)で入力してください。 role.notFound=ロールにはadmin以外登録出来ません。 mailAddress.duplicated=入力されたメールアドレスは登録済みです。 add.success={0}の登録を完了しました。
サンプル全体は validation-sample を参照してください。