수정 폼에 입력한 데이터를 db에 저장해보자
클라이언트에서 서버로 데이터를 전송할 때 HTTP를 사용한다
HTTP 메소드는 네가지가 있고 각각 CRUD를 위해 사용한다.
SQL의 쿼리도 마찬가지
서버를 재시작 할 때마다 데이터를 새로 만들어줘야 해서 귀찮다.
이걸 해결하기 위해 더미 데이터를 만들자
insert into article(id, title, content) values(1, '가가가가', '1111');
insert into article(id, title, content) values(2, '나나나나', '2222');
insert into article(id, title, content) values(3, '다다다다', '3333');
resources 디렉토리 아래 data.sql을 만들고 이렇게 데이터 3개를 만들어 준다.
spring.h2.console.enabled=true
spring.jpa.defer-datasource-initialization=true
그리고 나서 application.properties에 아래 코드를 추가해줘야 한다. 그래야 data.sql이 적용된다.
이렇게 하면 자동으로 서버를 재시작 할 때마다 데이터 3개가 생성된다.
{{>layouts/header}}
{{#article}}
<form action="/articles/update" method="post">
<input type="hidden" name="id" value="{{id}}">
<input type="text" name="title" value="{{title}}">
<br>
<textarea cols="30" rows="10" name="content">{{content}}</textarea>
<button type="submit">제출</button>
<a href="/articles/{{id}}">Back</a>
</form>
{{/article}}
{{>layouts/footer}}
edit.mustache를 이렇게 수정했다.
articles/update로 폼 데이터를 보내도록 했다.
그리고 보내는 method는 form 태그가 get이랑 post방식밖에 지원을 하지 않아서 post 방식을 이용했다.
또한 id 정보 또한 보내기 위해 hidden 인 input 태그를 만들어서 id 정보를 보냈다.
package com.example.firstproject.dto;
import com.example.firstproject.entity.Article;
import lombok.AllArgsConstructor;
import lombok.ToString;
@AllArgsConstructor
@ToString
public class ArticleForm {
private Long id;
private String title;
private String content;
public Article toEntitiy() {
return new Article(id,title,content);
}
}
데이터를 던질 때 입력 폼의 데이터니까 dto를 이용해서 던지는데 id도 던지니까 dto 객체에 id 필드를 만들어줬다.
그리고 엔티티로 변경하는 toEntitiy 메소드에도 매개변수로 id를 받도록 했다.
package com.example.firstproject.controller;
import com.example.firstproject.dto.ArticleForm;
import com.example.firstproject.entity.Article;
import com.example.firstproject.repository.ArticleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Controller
@Slf4j //로깅을 위한 어노테이션
public class ArticleController {
@Autowired // 스프링부트가 미리 생성한 객체를 가져다가 연결
private ArticleRepository articleRepository;
@GetMapping("/articles/new")
public String newArticleForm(){
return "articles/new";
}
@PostMapping("articles/create")
public String createArticle(ArticleForm form){
// System.out.println(form.toString());
// 로깅 기능으로 println 대체하자
log.info(form.toString());
// 1. DTO를 Entitiy로 변환해야한다
Article article = form.toEntitiy();
//System.out.println(article.toString());
log.info(article.toString());
// 2. Repository에게 Entitiy를 DB안에 저장하게 한다
Article saved = articleRepository.save(article);
//System.out.println(saved.toString());
log.info(saved.toString());
return "redirect:/articles/"+saved.getId();
}
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model){
log.info("id = "+id);
//1. id로 데이터를 가져옴
//orElse로 해당 id값이 없다면 null을 반환
Article articleEntitiy = articleRepository.findById(id).orElse(null);
//2. 가져온 데이터를 모델에 등록
model.addAttribute("article",articleEntitiy);
//3. 보여줄 페이지를 설정
return "articles/show";
}
@GetMapping("/articles")
public String index(Model model){
//1. 모든 Article을 가져온다
List<Article> articleEntityList = articleRepository.findAll();
//2. 가져온 Article 묶음을 뷰로 전달한다.
model.addAttribute("articleList",articleEntityList);
//3. 뷰페이지를 설정한다
return "articles/index"; //articles/index.mustache가 보이도록
}
@GetMapping("/articles/{id}/edit")
public String edit(@PathVariable Long id, Model model){
//수정할 데이터 가져와야한다
Article articleEntitiy = articleRepository.findById(id).orElse(null);
//모델에 데이터 등록
model.addAttribute("article",articleEntitiy);
return "articles/edit";
}
@PostMapping("/articles/update")
public String update(ArticleForm form){
log.info(form.toString());
//1. DTO를 엔티티로 변환한다
Article articleEntity = form.toEntitiy();
log.info(articleEntity.toString());
//2. 엔티티를 DB로 저장한다
//2-1 : DB에서 기존 데이터를 가져온다
Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
//2-2 : 기존 데이터 값을 수정한다
if (target!=null) {
articleRepository.save(articleEntity); //엔티티가 db로 갱신
}
//3. 수정 결과 페이지로 리다이렉트 한다
return "redirect:/articles/"+articleEntity.getId();
}
}
컨트롤러의 update 메소드이다.
먼저 DTO를 엔티티로 변환해야 한다.
toEntitiy 메소드로 변환해준다.
그리고 엔티티를 DB에 저장해야 한다.
리포지토리에서 findById를 이용해서 기존 데이터를 찾는다
기존 데이터를 찾는 이유는 기존 데이터가 있을 경우에만 save로 갱신할 거여서..
기존 데이터가 있다면 (null)이 아니라면 리포지토리에 save로 아까 만든 엔티티를 저장해준다. (기존 데이터가 있으면 save는 업데이트해줌)
그리고 return에 상세 페이지를 리다이렉트 하게 해서 수정하고 나면 상세 페이지가 보이게 한다.
/h2-console로 들어가서 이렇게 sql 문법을 사용해서 직접 데이터를 업데이트 할 수도 있다.