[JPA]DB,Entity의 연관관계 & Entity의 방향관계

Sunghun Kim·2024년 11월 5일

Jpa

목록 보기
5/10

1. DB 테이블간의 연관관계

  • 연관 관계 고민

    • 고객이 음식을 주문 시, 주문 정보는 어느 테이블에 들어가야 할까요?
      • 고객 테이블? 음식 테이블?
    1. 고객 테이블

      • 한명의 고객은 음식을 여러개를 주문할 수 있습니다.

        • 고객과 음식은 1 대 N 관계입니다.
      • 주문한 음식의 정보를 파악하기 위해 food_id 컬럼을 추가합니다.

      • 고객 테이블에 주문 정보를 넣습니다.

        idnamefood_id
        1Robbie1
        2Robbert1
        3Robbie2
      • Robbie는 후라이드 치킨, 양념 치킨을 주문했습니다.

      • 불필요하게 고객의 이름이 중복되는 문제가 발생합니다.

    2. 음식 테이블

      • 하나의 음식은 여러명의 고객에게 주문될 수 있습니다.

        • 음식과 고객은 1 대 N 관계입니다.
      • 주문한 고객의 정보를 파악하기 위해 user_id 컬럼을 추가합니다.

      • 음식 테이블에 주문 정보를 넣습니다.

        idnamepriceuser_id
        1후라이드 치킨150001
        2후라이드 치킨150002
        3양념 치킨200001
      • 후라이드 치킨을 여러사람이 주문하게되었을 때!

      • 불필요하게 음식의 이름이 중복되는 문제가 발생합니다.

        IDnamepriceuser_id
        1후라이드치킨150001,2
      • 그렇다면 위 표처럼 ‘데이터베이스에 저장될 때 user_id 컬럼에 1,2 로 저장하면 되지 않을까?’라고 생각할 수도 있지만!

      • user_id 값을 계속해서 추가할 때 뿐만 아니라 고객의 정보도 함께 조회가 필요할 때 많은 문제가 발생할 수 있기 때문에 현실적으로 불가능합니다.

    3. 주문 테이블

      • 주문에 대한 정보를 기록할 orders 테이블을 추가합니다.

      • 주문 테이블을 사용하여 테이블들의 연관 관계를 해결합니다.

      • 고객

        idname
        1Robbie
        2Robbert
      • 음식

        idnameprice
        1후라이드 치킨15000
        2양념 치킨20000
        3고구마 피자30000
        4아보카도 피자50000
      • 주문

        iduser_idfood_id주문일
        1112023-01-01
        2212023-01-01
        3222023-01-01
        4142023-01-01
        5232023-01-01
      • 고객 1명은 음식 N개를 주문할 수 있습니다.

        • 고객 : 음식 = 1 : N 관계
      • 음식 1개는 고객 N명에게 주문될 수 있습니다.

        • 음식 : 고객 = 1 : N 관계
      • 결론적으로 고객과 음식은 N : M 관계입니다.

        • 고객 : 음식 = N : M 관계
      • 이렇듯 N : M 관계인 테이블들의 연관 관계를 해결하기 위해 orders 테이블처럼 중간 테이블을 사용할 수 있습니다.

      • 고객 1명은 주문을 여러번 할 수 있습니다.
        - 고객 : 주문 = 1 : N

      • 음식 1개는 주문이 여러번 될 수 있습니다.
        - 음식 : 주문 = 1 : N

2. DB 테이블의 방향

  • DB table간의 방향
    • DB 테이블들간의 관계에서 방향의 개념이 존재할까요?(없다)
      • 방향에는 크게 단방향과 양방향을 생각해 볼 수 있습니다.
        • 예를 들어 단방향은 users 테이블에서만 food 테이블을 참조할 수 있을 때를 의미합니다.
        • 양방향은 users 테이블과 food 테이블이 서로를 참조할 수 있을 때를 의미합니다.
        • 그렇다면 DB 테이블간의 방향이 있는 게 맞을까요?
    • 고객 ID가 1인 사람이 주문한 음식 정보를 users 테이블 기준으로 조회해보겠습니다.
      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 테이블 기준으로는 고객 ID가 1인 사람이 주문한 음식 정보를 조회할 수 없는 걸까요?
      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;
    • DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있습니다.
      • 이처럼 DB 테이블간의 관계에서는 방향의 개념이 없습니다.

3. Entity의 연관관계 - 단, 양방향 관계

  • Entity간의 연관 관계
    • 그렇다면 JPA Entity에서는 이러한 테이블간의 연관 관계를 어떻게 표현하고 있을까요?
    • DB에는 이런 개념이 없지만 한 Entity에서 조회를 하려면 다른 Entity 필드 정보가 있어야 가능해 이런 관계가 있다.

    양방향 관계

    • 음식 : 고객 = N : 1 관계를 표현해보겠습니다.
      • 음식
        @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
        @Table(name = "users")
        public class User {
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private Long id;
            private String name;
        
            @OneToMany(mappedBy = "user")
            private List<Food> foodList = new ArrayList<>();
        }
      💡 DB에 위처럼 데이터가 여러가지 한번에 저장되지는 않지만 조회를 위한 Entity, JPA에서의 표현 방법이다.
  • 한명의 고객은 여러번 주문이 가능한 상황입니다.
    - 이를 Entity에서 여러번 가능함을 표현하기 위해 Java Collection을 사용하여 List<Food> foodList = new ArrayList<>() 이처럼 표현할 수 있습니다.

    • 그렇다면 Entity에서 이렇게까지 해서 표현을 하는 이유가 무엇일까요?

      • DB 테이블에서는 고객 테이블 기준으로 음식의 정보를 조회하려고 할 때 JOIN을 사용하여 바로 조회가 가능하지만 고객 Entity 입장에서는 음식 Entity의 정보를 가지고 있지 않으면 음식의 정보를 조회할 방법이 없습니다.

      • 따라서 DB 테이블에 실제 컬럼으로 존재하지는 않지만 Entity 상태에서 다른 Entity를 참조하기 위해 이러한 방법을 사용합니다.

    • 현재 음식 Entity와 고객 Entity는 서로를 참조하고 있습니다.

      • 이러한 관계를 양방향 관계라 부릅니다.

단방향 관계

  • 음식

    @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
    @Table(name = "users")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
    }
  • 음식 Entity에서만 고객 Entity를 참조할 수 있습니다.

    • 이러한 관계를 단방향 관계라 부릅니다.
    • 고객 Entity에는 음식 Entity의 정보가 없기 때문에 음식 정보를 조회할 수 없습니다.
  • <정리>

    • DB 테이블에서는 테이블 사이의 연관관계를 FK(외래 키)로 맺을 수 있고 방향 상관없이 조회가 가능합니다.
    • Entity에서는 상대 Entity를 참조하여 Entity 사이의 연관관계를 맺을 수 있습니다.
    • 하지만 상대 Entity를 참조하지 않고 있다면 상대 Entity를 조회할 수 있는 방법이 없습니다.

따라서 Entity에서는 DB 테이블에는 없는 방향의 개념이 존재합니다.

DB 테이블 사이의 관계 Vs Entity 클래스 사이의 관계 차이

  • DB 테이블에는 이 방향이라는 개념이 없지만 Entity 클래스 세계에서는 객체 형태이기 때문에 서로 참조하기 위해 상대 엔티티의 타입을 필드로 이렇게 가지고 있어야만 합니다.

  • 그렇기 때문에 그런 참조할 만한 필드가 없다면 조회가 불가능한 상황이 발생을 해서 방향이라는 개념이 생기게 되었다.

  • 그래서 서로 상대방의 엔티티를 참조하고 있다면 양방향.

  • 한쪽이라도 참조하지 못하고 있다면 단방향이란 표현을 사용한다라고 정리를 하면 될 것 같다.

profile
BackEnd Developer!!

0개의 댓글