7.0 7주차 워크북 학습 목표
스프링 프로젝트 진행 시
인프라 구축이 완료되면 (12주차에서 다룸),
앞서 설계한 ERD를 통해 Spring Data JPA로 Entity를 설계해야 한다.
이번 주차에서는 앞서 설계한 미션 ERD를 따라
JPA Entity 매핑을 해보자.
1) Spring data JPA를 이용해서 Entity 설계, 매핑하기
사용할 음식점 미션 프로젝트 ERD는 아래와 같다.
7.1 Springboot 디렉토리 컨벤션
프로젝트 마다 디렉토리 컨벤션은 달라질 수 있지만,
해당 프로젝트에서는 아래와 같이 package 를 만들어 주었다.
(github action을 위한 디렉토리는 생성하지 않음)
각각의 패키지에 대해 하나씩 자세하게 알아보자.
domain 패키지
- JPA에서 사용하기 위한 Entity 클래스를 저장
controller 패키지
- HTTP 요청에 따른 응답을 주는 클래스 모임
- 응답을 주는 과정은 service에서 처리
service 패키지
- 비즈니스 로직이 필요한 클래스 모임
- controller > service > repository 메소드 호출
repository 패키지
- 데이터베이스와 통신
- Spring Data JPA를 이용한 respository 이용
dto 패키지
- 클라이언트가 body에 담아서 보내는 데이터를 받음
- 데이터베이스에서 받아온 데이터를 클라이언트에게 보여줌
[ 추가 ] 왜 dto 패키지를 설정해야 할까?
- 요구사항 변경이 생겨 데이터베이스 테이블 설계가 바뀔 수 있음
- 이때 엔티티 그대로 응답을 주면 프론트까지 문제 발생 가능
- dto를 통해 데이터베이스 변경이 생긴 경우 dto만 변경 가능
converter 패키지
- 데이터 형식 간의 변환 수행
- repository에서 받아온 엔티티를 dto로 바꾸는 과정 수행
- Entity 생성 수행
(Service에서 수행할 수도 있지만, converter에서 하는 것이 단일 책임 원칙 측면에서 더 좋음)
- dto를 만드는 역할만 수행한다면, web 패키지 내부에 존재해도 됨
[ 추가 ] dto를 어디에서 생성해야 할까?
1) service에서 dto 생성
- service에서 controller로 dto 생성한 후, 이를 controller에 리턴함
- controller가 entity에 노출되지 않아 보안 측면에서 좋음
- 대규모 프로젝트에서 작업을 나누어 하는 경우, 해당 권한이 있는 개발자만 데이터를 볼 수 있도록 함
2) controller에서 dto 생성
- service에서 entity를 리턴하고, controller에서 controller로 dto를 만들어서 응답
- service의 범용성이 커져 유지보수가 편함
- 서비스 함수를 재활용 할 수 있어 코딩이 간편해짐
[ 참고 ] IntelliJ에서 사용하면 좋은 플러그인
- atom material Icons
- Settings > Plugin > Marketplace 에서 설치 가능
7.2 데이터베이스 생성하기
domain 패키지에서 entity를 매핑하는 방법을 알아보자.
RDS를 사용하면 요금 폭탄을 맞을 수 있기 때문에...
로컬 DB를 사용하였다.
먼저 mysql 워크밴치에서 umcstudy라는 데이터베이스를 생성하였다.
이후 resources 파일의 application.properties를 삭제하고
application.yml 파일을 생성해두었다.
application.yml 파일에 아래의 코드를 작성해준다.
(앞서 6주차의 build.gradle 파일에서 주석처리 했던 부분도 없애준다)
spring:
datasource:
url: jdbc:mysql://localhost:3306/데이터베이스이름
username: 유저 이름
password: 비밀번호
driver-class-name: com.mysql.cj.jdbc.Driver
sql:
init:
mode: never
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
show_sql: true
format_sql: true
use_sql_comments: true
hbm2ddl:
auto: update
default_batch_fetch_size: 1000
7.3 Entity 매핑하기
먼저 Member 엔티티를 통해 Entity 매핑 방법에 대해 알아보자.
아래의 ERD를 참고하여 엔티티를 생성하였다.
domain 패키지 > Member 클래스에
아래의 코드를 작성한다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.enums.Gender;
import umc.spring.domain.enums.MemberStatus;
import umc.spring.domain.enums.SocialType;
import javax.persistence.*;
import java.time.LocalDate;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private String specAddress;
@Enumerated(EnumType.STRING)
private Gender gender;
@Enumerated(EnumType.STRING)
private SocialType socialType;
@Enumerated(EnumType.STRING)
private MemberStatus status;
private LocalDate inactiveDate;
private String email;
private Integer point;
}
기본 어노테이션 작성
- @Entity : 해당 클래스가 JPA 엔티티임을 명시
- @Getter : lombok에서 제공, getter를 만들어 줌
- @Builder / @NoArgsConstructor(access = AccessLevel.PROTECTED)/@AllArgsConstructor
: 빌더패턴(자바의 디자인 패턴)을 사용하여 객체 생성
[ 참고 ] 빌더 패턴(Builder Pattern) 이란?
- GoF 디자인 패턴 중 생성 패턴에 해당
- 객체의 생성 클래스와 표현하는 클래스를 분리
- 필요한 데이터만 설정할 수 있어, 테스트가 용이하고 불필요한 코드의 양이 줄어듦
- 유연성 확보 가능
- 직관적으로 어떤 데이터에 어떤 값이 들어가는지 쉽게 파악 가능
- Setter는 불필요한 변경을 열어두지만, 빌더는 변경가능성을 최소화함
기본 키 만들기
- @Id : 기본 키 id 값임을 표
- @GeneratedValue(strategy = GenerationType.IDENTITY) : JPA가 통신하는 DBMS 방식을 따름
( 위의 예시에서는 MySQL을 따름)
특정 값 저장 하는 경우 ( Gender / Status / SocialType )
- 어떤 값이 저장될지 모르는 것이 아니라, 정해진 값들 중 특정 값이 저장되는 경우
- String 보다 enum 타입을 사용하는 것이 좋음
- @Enumerated(EnumType.STRING)을 사용하여 엔티티에 적용
- EnumType을 STRING으로 설정하는 것이 좋음
- ORIDINAL 을 사용하면 enum의 순서가 저장되어, 순서를 바꾸게 되면 에러 발생
Enum 클래스를 생성하는 방법은 아래와 같다.
domain 패키지 > enums 패키지에
아래와 같이 미리 정해진 값을 저장해준다.
package umc.spring.domain.enums;
public enum Gender {
MALE, FEMALE
}
package umc.spring.domain.enums;
public enum MemberStatus {
ACTIVE, INACTIVE
}
package umc.spring.domain.enums;
public enum SocialType {
KAKAO, GOOGLE, NAVER, APPLE
}
[ 참고 ]
Spring data JPA를 사용하면 specAddress를 spec_address 형식으로 자동으로 바꾸어준다!
이제 N : M 관계의 매핑 테이블을 제외하고
나머지 엔티티를 생성해보자.
코드 작성방법은 위의 Member 엔티티 작성 방식과 동일하다.
(created_at과 updated_at은 아래에서 따로 설정)
FoodCategory
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class FoodCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Mission
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDate;
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Mission {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer reward;
private LocalDate deadline;
private String missionSpec;
}
Region
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Region {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
Review
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String body;
private Float score;
}
Store
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Store {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private Float score;
}
Terms
package umc.spring.domain;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Terms {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String body;
private Boolean optional;
}
7.4 Created_at / Updated_at
Created_at 과 Updated_at의 경우 모든 엔티티에서 사용되므로,
일일이 Entity에 적용하지 않고,
추상 클래스를 만든 후 상속받도록 해보자.
domain 패키지 > common 패키지를 생성하고
BaseEntity 라는 추상클래스를 만든 후, 아래와 같이 코드를 작성한다.
package umc.spring.domain.common;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public abstract class BaseEntity {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
이후 모든 엔티티 클래스들이
BaseEntity 추상 클래스를 상속받도록 해준다.
또한 Spring boot Application 에서 JpaAuditing이 사용 가능하도록
아래와 같이 코드를 변경해준다.
package umc.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
7.5 매핑 테이블의 설계
앞서 작성하지 않았던 N : M 관계의 매핑 테이블은
mapping 패키지를 따로 만들어 관리해보자.
domain 패키지 > mapping 패키지에 각각의 엔티티를
위의 방식과 동일하게 작성한다.
MemberAgree 엔티티
package umc.spring.domain.mapping;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberAgree extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
MemberStatus Enum
- 회원 상태는 특정한 값을 지정하는 것이므로, enum을 생성하여 관리한다.
- domain 패키지 > enums 패키지에 MissionStatus enum 생성
package umc.spring.domain.enums;
public enum MissionStatus {
CHALLENGING, COMPLETE
}
MemberMission 엔티티
package umc.spring.domain.mapping;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.enums.MemberStatus;
import umc.spring.domain.enums.MissionStatus;
import javax.persistence.*;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberMission extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private MissionStatus missionStatus;
}
MemberPrefer 엔티티
package umc.spring.domain.mapping;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberPrefer extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
7.6 연관 관계 매핑
연관 관계 매핑의 단방향 매핑과 양방향 매핑에 대해
하나씩 자세하게 알아보자.
단방향 매핑
- 연관 관계 주인에게만 연관 관계를 주입
[ 추가 ] 연관 관계 주인이란?
데이터베이스에서 외래키를 가지는 테이블을 의미
앞선 ERD 예시를 통해 알아보자.
member_prefer 엔티티의 경우,
member 엔티티에서 member id를 / food_category에서 category_id
외래키를 가지고 있다.
이때 1 : N 관계에서 N에 해당되는 member_prefer 엔티티는 연관 관계 주인이 되고,
만약 1 : 1 관계라면 원하는 엔티티를 연관 관계 주인으로 설정할 수 있다.
앞서 작성한 member_prefer 엔티티에서
연관관계 매핑 코드를 추가해보자.
package umc.spring.domain.mapping;
import lombok.*;
import umc.spring.domain.FoodCategory;
import umc.spring.domain.Member;
import umc.spring.domain.common.BaseEntity;
import javax.persistence.*;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberPrefer extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id")
private FoodCategory foodCategory;
}
1) @ManytoOne
- 1 : N 관계에서 N에 해당하는 엔티티가 연관 관계 매핑할 때 사용
2) fetch = FetchType.LAZY
- 지연 로딩을 성정
3) @JoinColumn
- 외래키의 이름을 설정
MemberAgree 엔티티의 연관 관계 매핑 코드는 다음과 같다.
package umc.spring.domain.mapping;
import lombok.*;
import umc.spring.domain.Member;
import umc.spring.domain.Terms;
import umc.spring.domain.common.BaseEntity;
import javax.persistence.*;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberAgree extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "term_id")
private Terms terms;
}
Mission 엔티티의 연관 관계 매핑 코드는 다음과 같다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import javax.persistence.*;
import java.time.LocalDate;
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Mission extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer reward;
private LocalDate deadline;
private String missionSpec;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "store_id")
private Store store;
}
양방향 매핑
- 버그 발생 위험성이 있음
- 양방향 매핑을 통한 객체 그래프 탐색은 프로그래밍을 편리하게 도와줌
- 연관 관계 주인이 아닌 엔티티에게도 연관 관계 주입
- 필수적인 기능인 cascade 설정이 가능
- 연관 관계 편의 메서드 필요
[ 추가 ] cascade란?
- 데이터베이스에서 외래키를 가진 연관 관계 주인인 테이블에 설정
- 참조 대상 테이블의 칼럼이 삭제되거나 변경될 때, 같이 변경되는 기능
- JPA에서는 연관 관계 주인이 아닌, 참조 대상 엔티티에 설정
💡단방향 매핑에서는 변경되지 않아야 하는 데이터가 삭제될 수 있으므로, 양방향 매핑이 유리
Member 엔티티에 양방향 매핑을 적용한 코드는 다음과 같다.
1 : N 관계에서 1에 해당하는 엔티티에 설정해준다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.enums.Gender;
import umc.spring.domain.enums.MemberStatus;
import umc.spring.domain.enums.SocialType;
import umc.spring.domain.mapping.MemberAgree;
import umc.spring.domain.mapping.MemberMission;
import umc.spring.domain.mapping.MemberPrefer;
import javax.persistence.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String address;
private String specAddress;
@Enumerated(EnumType.STRING)
private Gender gender;
@Enumerated(EnumType.STRING)
private SocialType socialType;
@Enumerated(EnumType.STRING)
private MemberStatus status;
private LocalDate inactiveDate;
private String email;
private Integer point;
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberAgree> memberAgreeList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberPrefer> memberPreferList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<Review> reviewList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberMission> memberMissionList = new ArrayList<>();
}
1) @OneToMany
- 1 : N 관계에서 N에 해당하는 엔티티에서 ManytoOne이 설정된 멤버 변수를 mappedBy
2) @CascadeType.ALL
- Member의 변화에 따라 각 엔티티가 영향을 받게됨
- Member 에서 삭제되는 데이터가 있으면, 같이 삭제가 되므로 일일이 삭제하지 않아도 됨
Terms 엔티티의 양방향 매핑 코드는 다음과 같다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.mapping.MemberAgree;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Terms extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String body;
private Boolean optional;
@OneToMany(mappedBy = "terms", cascade = CascadeType.ALL)
private List<MemberAgree> memberAgreeList = new ArrayList<>();
}
Mission 엔티티의 양방향 매핑 코드는 다음과 같다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.mapping.MemberMission;
import javax.persistence.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Mission extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer reward;
private LocalDate deadline;
private String missionSpec;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "store_id")
private Store store;
@OneToMany(mappedBy = "mission", cascade = CascadeType.ALL)
private List<MemberMission> memberMissionList = new ArrayList<>();
}
FoodCategory 테이블의 경우 주로 수정, 삭제가 일어나지 않으므로
양방향 매핑을 수행하지 않았다.
7.7 칼럼 별 세부적인 설정
앞서 ERD에서 Member 테이블의 name의 경우 varchar(20)으로 설정하였지만,
우리는 JPA에서 단순히 String으로 설정해 놓았다.
unique / default / null 가능 / Type 등
각 칼럼의 세부적인 설정을 완성해보자.
Member 테이블의 세부 설정 예시는 다음과 같다.
package umc.spring.domain;
import lombok.*;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.enums.Gender;
import umc.spring.domain.enums.MemberStatus;
import umc.spring.domain.enums.SocialType;
import umc.spring.domain.mapping.MemberAgree;
import umc.spring.domain.mapping.MemberMission;
import umc.spring.domain.mapping.MemberPrefer;
import javax.persistence.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 20)
private String name;
@Column(nullable = false, length = 40)
private String address;
@Column(nullable = false, length = 40)
private String specAddress;
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "VARCHAR(10)")
private Gender gender;
@Enumerated(EnumType.STRING)
private SocialType socialType;
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "VARCHAR(15) DEFAULT 'ACTIVE'")
private MemberStatus status;
private LocalDate inactiveDate;
@Column(nullable = false, length = 50)
private String email;
private Integer point;
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberAgree> memberAgreeList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberPrefer> memberPreferList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<Review> reviewList = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberMission> memberMissionList = new ArrayList<>();
}
1) @Column
- 해당 어노테이션을 통해 칼럼 세부 설정이 가능하다.
2) columnDefinition = "VARCHAR(10)" / nullable = false, length = 40
- enum 타입의 경우 전자로 설정함
3) 'ACTIVE'
- @ColumnDefault('ACTIVE')으로도 작성 가능
- mySQL 문자열은 ' '로 감싸지 않으면 DDL을 날려 오류 발생
설정을 완료한 후 application.yml 파일의 auto를 create로 변경한다.
이후 Spring boot를 실행하면 @Entity를 찾아 Database에 테이블을 생성한다.
로그를 확인해보면 실제로 테이블이 생성된 것을 확인할 수 있다.
에러 메시지가 발생할 수 있는데,
이는 기존 테이블이 없는데 create으로 삭제 후 생성하다보니 발생하는 오류이므로
무시하고 다시 실행하면 된다.
단 create는 매번 새로운 테이블을 생성하니,
이후에는 update로 변경해야 한다.
최용욱 'UMC Server 7주차 워크북' 내용을 기반으로 작성하였습니다.
'[UMC Ewha 5th] Server - SpringBoot' 카테고리의 다른 글
[UMC Server] Chapter 8.1 API 응답 통일 (2) | 2023.11.27 |
---|---|
[UMC Server] Chapter 6. API URL의 설계 & 프로젝트 세팅 (0) | 2023.11.15 |
[UMC Server] Chapter 5. 실전 SQL - 어떤 Query를 작성해야 할까? (0) | 2023.11.07 |
[UMC Server] Chapter 4. Database 설계 & AWS RDS 설정 (1) | 2023.11.01 |
[UMC Server] Chapter 3. Web Server & Web application Server(WAS), Reverse Proxy (1) | 2023.10.09 |