컨트롤러에서 DTO로 받아온 데이터를 데이터베이스(DB)에 저장해보자. 데이터베이스란 데이터를 관리하는 창고이며, MySQL, Oracle, Postgres, H2 등이 있다. 여기서는 H2를 사용한다. server, 즉 Spring Boot는 Java를 사용하는 반면, DB는 SQL을 사용하므로 Java를 이해하지 못한다. 우리는 Java로 어떻게 DB에게 명령을 할 수 있을까? 이를 위한 도구가 바로 JPA이다. JPA는 Java 언어를 DB가 이해할 수 있게끔하고 data 관리에 필요한 여러 기능들까지 제공한다. 이러한 JPA의 핵심 도구에는 Entity와 Repository가 있다. Java 객체 DTO를 DB가 이해할 수 있도록 규격화된 data인 Entity는 Repository라는 일꾼을 통해 DB에게 전달되고 처리된다.
지금부터 DTO를 Entity로 변환하고 Repository를 통해서 DB에 저장되는 과정까지 연습을 해보자.
DTO에 받아온 데이터를 DB에 저장하는 흐름은 아래와 같다.
앞서 작성한 ArticleController에서 form 데이터를 Entity로 변환하도록 하자.
@PostMapping("/articles/create")
public String createArticle(ArticleForm form) {
// 1. Entity로 변환
Article article = form.toEntity();
System.out.println(article.toString());
return "";
}
현재 Article이라는 entity의 클래스가 정의되지 않았고, toEntity 메소드 또한 존재하지 않는다.
먼저 Article이라는 클래스를 추가해보자.
entity라는 package를 새로 생성하면 Article이라는 클래스가 생성된 것을 확인할 수 있다. 이제 entity 클래스를 작성해보자.
package com.example.project1.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity // DB가 해당 객체를 인식하게 함.
public class Article {
// Entity에는 자신을 구분짓는 대표값이 존재해야함. 주민번호 같은 개념
@Id // 대표값을 지정
@GeneratedValue // id를 자동 생성 (1, 2, 3...)
private Long id;
// title, content 2개의 field 추가
@Column // title과 content를 DB가 이해하도록. 즉, DB에서 관리하는 table에 연결되도록.
private String title;
@Column
private String content;
// Entity를 만들기 위한 생성자 추가
public Article(Long id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
해당 위치에 toEntity 메소드를 작성하도록 하자.
public Article toEntity() {
// Article(Entity) 객체 반환
return new Article(null, title, content);
}
우선, repository가 있다는 가정 하에 컨트롤러에 코드를 추가 작성해보자.
@PostMapping("/articles/create")
public String createArticle(ArticleForm form) {
// 1. Entity로 변환
Article article = form.toEntity();
// 2. Repository에게 entity를 DB 안에 저장하도록 함.
// repository가 DB에 저장한 데이터를 최종적으로 Article이란 entity 타입으로 반환
Article saved = articleRepository.save(article);
return "";
}
현재 ArticleRepository 클래스가 정의되지 않았으므로 작성해보도록 하자.
src -> main -> java -> 기본 패키지 아래 repository라는 패키지를 생성한 후, 이름이 ArticleRepository인 interface를 생성한다. Repository를 직접 구현할 수도 있겠지만 JPA에서 제공하는 repository interface를 활용해서 쉽게 만들어보도록 하자.
package com.example.project1.repository;
import com.example.project1.entity.Article;
import org.springframework.data.repository.CrudRepository;
public interface ArticleRepository extends CrudRepository<Article, Long> {
}
CrudRepository라는 interface를 상속받아오면 CrudRepository가 제공하는 save하고, 읽고, 쓰고, 수정하고, 삭제하는 기능 등을 구현없이 사용할 수 있다.
CrudRepository<관리 대상 entity, 관리 대상 entity의 대표값 type>
다시 컨트롤러로 돌아오면 ArticleRepository 클래스와 save 메소드에 에러가 발생했던 게 없어진 걸 확인할 수 있다. save()는 CrudRepository에서 제공하는 기능이다.
아래는 컨트롤러의 전체 소스 코드이다. 데이터가 어떻게 entity로 변환되어 저장되는지 확인해보자.
package com.example.project1.controller;
import com.example.project1.dto.ArticleForm;
import com.example.project1.entity.Article;
import com.example.project1.repository.ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class ArticleController {
@Autowired // Spring Boot가 미리 생성해놓은 객체를 가져다 자동 연결
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());
// 1. Entity로 변환
Article article = form.toEntity();
System.out.println(article.toString());
// 2. Repository에게 entity를 DB 안에 저장하도록 함.
// repository가 DB에 저장한 데이터를 최종적으로 Article이란 entity 타입으로 반환
Article saved = articleRepository.save(article);
System.out.println(saved.toString());
return "";
}
}
첫 줄은 DTO에 저장된 데이터의 모습이다.
두 번째 줄은 DTO가 entity로 변환된 모습이다.
세 번째 줄은 repository가 DB에 entity를 저장한 형태의 모습이다. 이때 id는 자동 생성된다.