こんにちは、くまごろーです。
ポートフォリオ(家計簿アプリ)にめちゃくちゃ苦戦しています。
さっきまで本当にしょうもないミスに悩まされてたんで、今回はそれをまとめようと思います。
エンティティのフィールド型を変えたせいで、えらい目にあってしまいました。
また、エラーを解消する過程で、Thymeleafはth:fieldやth:nameに値を入れているとvalueの中が空になるという恐ろしい事実も知ることができました(=_=)
1 どんな状況?
(1)問題の部分
今回問題が起きたのは、家計簿アプリの出入金登録処理を行う部分です。
現況のviewはこんな感じで、この画面から
- 日付
- 金額
- カテゴリID
をコントローラーに送信するようになっています。
(2)エンティティクラスのフィールドの型を変更した
↓のクラス、家計簿アプリの出入金を管理するためのエンティティクラスなんですが、
<MoneyRecord.java>
public class MoneyRecord{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @NotNull @Column(name = "record_id") private int recordId; @NotNull @Column(name = "user_id") private long userId; ~以下略~ }
@NotNull @Column(name = "user_id") private int userId;
ここの部分を
@NotNull @Size(min = 4, max = 20) @Column(name = "user_id") private String username;
このように変更しました。
int型→String型に変えました。この時はこれが問題の原因になるとは露とも知らず・・・
(3)出入金登録処理を実行すると、BindingResultがエラーを検知する
(1)の修正を行うまでは起きなかったエラーが発生するようになりました。
@PostMapping("/post") public String process(@Validated @ModelAttribute MoneyRecord moneyRecord, BindingResult result, Authentication loginUser, Model model) { model.addAttribute("categories", categoryRepository.findAll()); model.addAttribute("user", userRepository.findByUsername(loginUser.getName())); if(result.hasErrors()) { return "post"; //ここでエラー判定 } ~略~ return "redirect:/main?post"; }
2 原因
なんでや( ゚Д゚)さっきまでできたのに何が悪いんや・・・と1時間くらいもがいてたのですが、さっき気づきました。
原因はusernameの型をintからStringに変更したことによるものでした。
- int型の初期値・・・0
- String型の初期値・・・null
@Notnullを付加した場合、int型では引っかからないが、String型だとnull判定になる。
今回、usernameはコントローラ側で取得する仕組みになっていました。int型にしていた時は初期値が0であったため、BindingResultのhasErrorsメソッドからは見逃されていたようです。それが、String型に変更したおかげで露見したと。
これJava Silver取ってなかったら永遠にわからなかったかもしれない(-"-)
3 どう対応したか
(1)hiddenタグを使用した
今回は、Thymeleafの方からusernameの値を送るようにしました。やり方がよくわからなかったので、無難にhiddenタグを使用しました。
(2)解決かと思いきや・・・
これで解決かと思いきや、いまだにエラーが解消されない・・・
なんでや、と思い色々検索してみたのですが、なんとth:fieldやth:nameに値を入れているとvalueの中が空になるというケースがあるらしいんです。
どういうことや( ゚Д゚)
というわけで、↓のようにコードを打ち換えました。
<input type="hidden" th:value="${user.username}" name="username">
これでやっと解決しました。
4 参考