Spring Bootを勉強していて、簡単な投稿アプリを作ろうとしていました。
そんな中で、投稿にユーザー情報を紐付けるのに苦労したので備忘録を載せます。
ただ、やり方として合ってるのか、適切なのかはイマイチよくわかりません。
初めはこんな風に書いて、きちんとユーザーを紐付けできてました
//投稿追加処理
@PostMapping(path="/post/add")
public String addNewPost(@ModelAttribute Post post, @RequestParam("file") MultipartFile file, @AuthenticationPrincipal(errorOnInvalidType=true) UserDetails user ) {
post.setUser((CustomUser)user);
storageService.store(file);
post.setImage("/files/"+file.getOriginalFilename());
postRepository.save(post);
return "redirect:/posts";
}
しかし、久々にプロジェクトを動かして投稿するとSQLでuser_idがnullだからエラーが起こるようになってしまったんです。
でも、デバックでこのように書いて"/"にアクセスするとターミナルにはきちんとログイン中のユーザー情報が取得できているんです。
//認証確認
@GetMapping
public String index(@AuthenticationPrincipal UserDetails user) {
System.out.println(((CustomUser)user).getId()); // ユーザー名を表示
System.out.println(user.getUsername()); // ユーザー名を表示
return "welcome";
}
AIに聞きながら色々試して、最終的に下記のようにすればエラー解消しました
@Autowired
private CustomUserRepository userRepository;
//投稿追加処理
@PostMapping(path="/post/add")
public String addNewPost(@ModelAttribute Post post, @RequestParam("file") MultipartFile file, @AuthenticationPrincipal(errorOnInvalidType=true) UserDetails user ) {
CustomUser dbUser = userRepository.findByUsername(user.getUsername()).orElseThrow(() -> new RuntimeException("User not found in DB"));
post.setUser(dbUser);
storageService.store(file);
post.setImage("/files/"+file.getOriginalFilename());
postRepository.save(post);
return "redirect:/posts";
}
ユーザー情報は取れているから、それを使ってDBでユーザー検索してその結果をリレーションで使うようにしています。
@AuthenticationPrincipalで取得する情報が古かったりすると
ユーザー情報の食い違いが起きてエラーになる可能性がありので、DBから取得したデータを使うのが
良いとの旨をAIが言ってました。
他のフレームワーク(larave,Django,rails)は簡単にユーザー情報紐付けできていたので、
なんだか手間なことをやってるようでいまいち腑に落ちませんが。