나만의블로그만들기(2)
전에 넣은 DB값들을 확인하는 과정을 구현해보았다.
게시글 확인하고 페이지 내에서 이동하기
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model){
Article articleEntity = articleRepository.findById(id).orElse(null);//원래는 findById를 하게 되면 Optional<Article>이 반환된다. 이를 해결하고자 orElse를 사용하게 된다.
model.addAttribute("article",articleEntity);
return "articles/show";
}
@PathVariable:을 활용하면 URL 요청으로 들어온 전달값을 컨트롤러의 매개변수로 가져올 수 있다.
원래는 findById를 하게 되면 Optional<Article>이 반환된다. 이를 해결하고자 orElse를 사용하게 된다.
@GetMapping("/articles")
public String index(Model model){
ArrayList<Article> articleList = articleRepository.findAll();
model.addAttribute("articleList",articleList);
return "articles/index";
}
article들의 목록들을 보여주고자 할 때의 메서드도 구현해보았다. articleRepository.findAll()을 하게 되면 기본적으로 Iterator 타입으로 반환하게 되어 ArrayList에 담게 되면 문제가 생기게 된다. 타입이 맞지 않기 때문인데
Iterator ----- Collection ------ List 순으로 상속받는 인터페이스 구조이기 때문에,
다운캐스팅을 사용하거나 articleList를 Iterator<Aritcle>형태로 받거나 articleRepository의 findAll메서드의 반환 값을 오버라이딩 하여 타입을 변환시켜주어야 한다.
나의 경우에는 오버라이드 해주어 반환 타입을 수정해주었다.
Iterator 의 구조에 관해 익숙해지는 것이 중요해보인다.
@PostMapping("/articles/create")
public String createArticle(ArticleForm form){
Article article = form.toEntity();
Article saved=articleRepository.save(article);
return "redirect:/articles/"+saved.getId();
}
만들게 되었을 때 각 텍스트로 이동하는 페이지를 만들어 주기 위해 redirect 해주었다.
- 클라이언트 요청
- 서버에서 리다이렉트
- 리다이렉트 주소로 가서 다시 요청
- 응답
이 구조로 이어지게 된다. 리다이렉트에서 각자의 값으로 이동시켜주기 위해 saved의 Id값을 가져오는 작업을 해주었다.
게시글 수정하기
@GetMapping("/articles/{id}/edit")
public String edit(@PathVariable Long id, Model model){
Article articleEntity = articleRepository.findById(id).orElse(null);
model.addAttribute("article",articleEntity);
return "articles/edit";
}
게시글 수정하기 위해 edit버튼을 눌렀을 때의 컨트롤러를 만들어 두었다.
이동한 컨트롤러에서 Id 와 Model를 매개변수로 받아 이를 다시 보여주게 된다.
@PostMapping("/article/update")
public String update(ArticleForm form){
Article article = form.toEntity();
Article target= articleRepository.findById(article.getId()).orElse(null);
if (target!=null){
articleRepository.save(article);
}
return "redirect:/aritcles/"+article.getId();
}
DTO형태로 폼데이터를 받아온 후에 이를 다시 엔티티로 만들어 준 후, target으로 현제 레파지토리에 일치하는 데이터가 존재하는지 확인한 후에 있다면 이를 다시 saved메서드를 사용하여 교체해주게 된다.
이때 궁금했던 점이 있다. saved하게 된다면 기존 Id 가 일치하는 값을 찾아서 자동으로 교체해준다는 점이다. primary key를 활용하여 편리한 것 같았다.
중간중간 서버를 재시작 하느라 데이터를 계속 추가해서 확인해야 하는 점이 있었는데 resource에서 새로운 data.sql 파일을 만들어서 사용하게 된다면 서버 재시작 함과 동시에 데이터를 넣어 줄 수 있어서 편리하다.
하지만 스브링 부트 2.5부터는 data.sql을 사용하여 데이터 초기화를 권장하지 않기 때문에
spring.jpa.defer-datasource-initialization=true
를 application.properties에 추가해주어야한다.
게시글 삭제하기
@GetMapping("/articles/{id}/delete")
public String delete(@PathVariable Long id, RedirectAttributes rttr){
Article target=articleRepository.findById(id).orElse(null);
if(target!=null){
articleRepository.delete(target);
rttr.addFlashAttribute("msg","삭제되었습니다.");
}
return "redirect:/articles";
}
HTML에는 GET,POST 메서드 밖에 지원하지 않기 때문에 일단은 URL로 접근하여 삭제해주는 방식으로 만들겠다.
delete할 경우에 해당 Id를 찾아와서 이를 삭제해주었다.
이 경우에서 리다이렉트로 돌아가게 해주는데 이때 삭제 된 알림을 알려주고 싶어서 RedirectAttributes를 사용하여 메시지를 던져주게 된다.
해당 매개변수는 일회성 데이터를 리다이렉트 페이지에게 던져주게 된다.
@GeneratedValue(GenerationType.IDENTITY)
원래 나의 코드에서는 @GeneratedValue로만 Id를 생성하게 끔 되어있었다 이는 1부터 차례로 1씩 증가하며 id를 넣어주게 되는 작업을 거치는데 만약에 내가 넣어 놓은 3개의 데이터가 있다면 id가 1에서 겹쳐지게 되는 것이다.
따라서 id를 DB가 알아서 자동으로 id를 생성하고 관리해주는 어노테이션을 적용시켜주는 것이다.