2/18(수) 엔티티 간의 관계

dev_joo·2026년 2월 18일

엔티티 간의 관계

프로젝트 생성

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/orderapp
spring.datasource.username=root
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true

database

create database orderapp;
user orderapp;

create table users
(
    id   bigint not null auto_increment,
    name varchar(255),
    primary key (id)
);


create table food
(
    id    bigint not null auto_increment,
    name  varchar(255),
    price float(53) not null,
    primary key (id)
);

DB 테이블에서의 연관관계

고객 테이블, 음식 테이블

🤵한 명의 고객은 여러 음식을🍗🍕🍔 주문할 수 있다.

  • Robbie는 후라이드 치킨을 주문했습니다.
  • Robbie는 양념 치킨을 주문했습니다.
### 불필요하게 중복된 값(고객 이름)을 가지게 된다.
ALTER TABLE food ADD user_id bigint;
INSERT INTO users (name, food_id) VALUES ('Robbie', 1);
INSERT INTO users (name, food_id) VALUES ('Robbert', 1);
INSERT INTO users (name, food_id) VALUES ('Robbie', 2);

🍗하나의 음식은 여러 고객에게👩‍💼🙋🏻🤵 주문될 수 있다.

  • 후라이드 치킨은 Robbie가 주문했습니다.
  • 후라이드 치킨은 Robbert가 주문했습니다.
### 불필요하게 중복된 값(음식 이름)을 가지게 된다.
ALTER TABLE food ADD user_id bigint;
INSERT INTO food (name, price, user_id) VALUES ('후라이드 치킨', 15000, 1);
INSERT INTO food (name, price, user_id) VALUES ('후라이드 치킨', 15000, 2);
INSERT INTO food (name, price, user_id) VALUES ('양념 치킨', 20000, 1);

고객과 음식은 N:M (多:多) 관계가 된다.

고객-음식
음식-고객

이는 하나의 같은 정보(고객-음식 연관관계)가 양쪽 테이블에 중복되어 분산되어있음을 의미한다.

주문 테이블 (중간 테이블)

이 중복을 해결하기 위해 양쪽에 테이블에 데이터를 추가하는 대신, 하나의 개념(주문) 테이블에 담아준다.

  • 1번 주문은 고객1이 시킨 1번 음식입니다.
  • 2번 주문은 고객2가 시킨 1번 음식입니다.
  • 3번 주문은 고객1이 시킨 2번 음식입니다.
create table orders
(
    id         bigint not null auto_increment,
    user_id    bigint,
    food_id    bigint,
    order_date date,
    primary key (id)
);

주문과 고객/음식은 1:N (1:다多) 관계가 된다.

고객:주문 = 1:N
음식:주문 = 1:M

DB 테이블 간의 방향

DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있기 때문에 테이블 간에는 방향이 없다.

# users 테이블에서 food 테이블을 참조
SELECT u.name as username, f.name as foodname, o.order_date as orderdate
FROM users u
         INNER JOIN orders o on u.id = o.user_id
         INNER JOIN food f on o.food_id = f.id
WHERE o.user_id = 1;

# food 테이블에서 users 테이블을 참조
SELECT u.name as username, f.name as foodname, o.order_date as orderdate
FROM food f
         INNER JOIN orders o on f.id = o.food_id
         INNER JOIN users u on o.user_id = u.id
WHERE o.user_id = 1;

Entity 간의 관계

JPA 에서는 이러한 Entity간의 연관 관계를 어떻게 표현하고 있을까?

1️⃣ 고객:음식 = 1:N = 양방향 관계

Entity 상태에서 다른 Entity를 참조하기 위해
하나의 엔티티가 다른 엔티티 타입의 필드를 포함하는 형태로 표현된다.
(이 관계가 DB 테이블에 실제 컬럼으로 존재하지는 않는다.)

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

	// Java 컬렉션을 사용하여 多관계를 표현
    @OneToMany(mappedBy = "user")
    private List<Food> foodList = new ArrayList<>();
}
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

	// User 엔티티를 포함
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

음식 Entity와 고객 Entity는 서로를 참조하고 있는데,
이러한 관계를 양방향 관계라 부른다.

2️⃣ 고객:음식 = 0:1 = 단방향 관계

User는 다른 엔티티를 포함하지 않는다.

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

FoodUser를 포함한다.

@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

음식 Entity에서만 고객 Entity를 참조할 수 있다.
이러한 관계를 단방향 관계라고 부른다.

profile
풀스택 연습생. 끈기있는 삽질로 무대에서 화려하게 데뷔할 예정 ❤️🔥

0개의 댓글