멋쟁이사자처럼 13기/정기 세션

[멋사/Mac OS] 4주차 정기 세션 (Part 2. 엔티티 설계)

개발자 지망생 리네 2025. 6. 18. 18:02

2. 엔티티 설계

(1) MySQL 접속하기

mysql -u root -p

 

-u root : 사용자 이름이 root

root 계정은 MySQL에서 최고 권한을 가진 관리자 계정.

- 데이터베이스 생성/삭제
- 사용자 계정 추가/삭제
- 권한 부여/회수
- 모든 테이블과 데이터에 접근 가능

 

-p: 비밀번호 입력

만일 비밀번호가 없다면 엔터를 누르면 된다.

(2) 데이터베이스 생성하기

CREATE DATABASE shop;
SHOW DATABASES;

 


(3) application.properties 파일 코드 작성

spring.application.name=shop

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/{DB 이름}?serverTimezone=UTC

# mysql username & password
spring.datasource.username={username}
spring.datasource.password={password}

# 실행 쿼리 출력
spring.jpa.properties.hibernate.show_sql=true

# 쿼리 포맷 설정
spring.jpa.properties.hibernate.format_sql=true

# 바인드 파라미터 출력
logging.level.org.hibernate.type.descripter.sql=trace

# 데이터베이스 초기화 전략 - DDL AUTO 옵션 사용
spring.jpa.hibernate.ddl-auto=create

# 데이터베이스 방언 설정
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

 

- 바인드 파라미터 출력

select * from user where id = ? -> select * from user where id = 1

 

<DDL AUTO>

- 데이터베이스 초기화 전략, Hibernate가 애플리케이션 실행 시 데이터베이스 테이블을 어떻게 처리할 지 결정하는 옵션

- 옵션에 따라 DDL(Data Definition Language)을 자동으로 작성하여 테이블을 생성

none create create-drop update validate
DDL 실행 안 함
(기본값, 배포 시 설정)
앱 실행 시 기존 테이블 삭제 후 새로 생성
(데이터 손실 발생 가능)
create와 동일하지만 앱 종료 시 테이블 삭제 테이블 구조만 변경하고 기존 데이터 유지 스키마 변경없이 테이블 구조가 맞는지 검증만 수행

(4) 연관관계

- 관계: 엔티티의 인스턴스 사이의 논리적 연관성, 데이터베이스 안에서 테이블간의 연결을 일컫음

- 연관관계: 관계를 객체 모델로 표현.

- 1:1, 1:N -> 단방향 관계, N:N -> 양방향 관계

- 단방향 관계 두 개를 통해 양방향 관계를 만들 수 있음

    ex) 학생 -> 동아리 + 학생 <- 동아리 = 학생 <-> 동아리

    => 우선 단방향으로 설정하고 필요에 따라 양방향으로 매핑을 추가하는 방식을 권장

 

- 양방향 관계인 경우 두 객체 중 하나로 외래 키를 관리해야하며, 관리하는 객체가 연관관계의 주인임

    -> 테이블에서 외래 키가 있는 객체를 주인으로 지정

    -> 외래키가 있는 곳이 N, 없으면 1 

    -> N쪽(@ManyToOne) / 1쪽(@OneToMany)

 

<다대다 연관관계>

- 관계형 DB는 정규화된 테이블 2개로 다대다 표현이 불가능함

- 연결 테이블을 추가해서 일대다 + 다대일 관계로 설정

- 테이블은 다대다 관계 구현이 불가능하지만 객체는 컬렉션을 통해 객체 2개로 다대다 관계 구현이 가능함

  (@ManyToMany, @JoinTable)

- 다대다 매핑 한계

   -> 주문시간, 수량과 같은 추가 데이터 항목을 연결 테이블에 넣을 수 없음

   -> 예상치 못한 쿼리 발생 가능

 


(5) Entity

- 데이터베이스의 테이블에 대응하는 클래스

- @Entity: JPA가 관리하는 엔티티

- @Table: 엔티티와 매핑할 테이블을 지정

- @Id: 테이블의 기본 키로 사용할 속성 지정

- @Column: 필드와 매핑할 컬럼명 지정

- @GeneratedValue: 기본 키 매핑 어노테이션(자동 생성)

- @Getter, @Setter, @ToString 메소드 자동 생성

package com.likelion13th.shop.entity;

import com.likelion13th.shop.dto.MemberFormDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import com.likelion13th.shop.constant.Role;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.time.LocalDateTime;

@Entity
@Table(name="member")
@Getter @Setter
@ToString
public class Member extends Base{

    // PK 설정
    @Id
    @Column(name="member_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Column(unique=true)
    private String email;
    private String password;
    private String address;

    @Enumerated(EnumType.STRING)
    private Role role;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String modifiedBy;
}

 

 

 

- enum 클래스 추가 (entity와 같은 경로에 constant 패키지 생성, role 클래스 추가)

package com.likelion13th.shop.constant;

public enum Role {
    USER, ADMIN
}

 

 

 

- 외래키 사용 예시

package com.likelion13th.shop.entity;

import com.likelion13th.shop.constant.OrderStatus;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name="orders")
@Getter @Setter
public class Order{
    @Id
    @Column(name="order_id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name="member_id", nullable = false)  
    private Member member;

    private LocalDateTime orderDate;
    private LocalDateTime createdBy;
    private LocalDateTime modifiedBy;

    @Enumerated(EnumType.STRING)
    private OrderStatus orderStatus;

    // 양방향 매핑
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> orderItemList = new ArrayList<>();
}