[SPRING] DB와 Entity 연관 관계의 차이

야부엉·2023년 11월 15일
0
post-thumbnail

1. DB table간의 연관 관계

1. DB 테이블의 관계 표현

  • 우선적으로 아래 그림과 같이 음식과 고객 테이블이 있다고 가정해보자.
  1. 고객 테이블 기준 음식이 1: N인 경우
  • 한 명이 여러 음식을 시킬 수 있다. 즉, 고객과 음식은 1 : N 관계라고 생각 해보면 우리는 아래의 그림과 같이 고객 테이블을 수정 할 수 있다.
  • 하지만 이 테이블에는 불필요하게 고객의 이름이 중복되는 문제가 발생한다.
  1. 음식 테이블 기준 고객이 1: N인 경우
  • 하나의 음식을 여러명이 시킬 수 있다. 즉, 음식과 고객은 1 : N 관계라고 생각 해보면, 아래의 그림과 같이 음식 테이블을 수정 할 수 있다.
  • 후라이드 치킨을 여러 명이 시켰을 경우, 불필요하게 음식의 이름이 중복되는 문제가 발생한다.
  1. 해결 방법
  • 위의 두 테이블의 문제점을 해결하기 위한 방법으로 우리는 아래의 그림과 같이 간단하게 배열을 생각 할 수 있다.
  • 하지만 배열을 쓸 경우 user_id 값을 계속해서 추가할 때 뿐만 아니라 고객의 정보도 함께 조회가 필요할 때 많은 문제가 발생할 수 있기 때문에 현실적으로 불가능하다.
  1. 주문 테이블을 따로 만들 경우
  • 위의 두 테이블만 비교했을 떄, 사실상 고객이랑 음식은 1 : N 관계인것이고, 옴식이랑 고객은 1 : N관계인 것을 알 수 있다.
    즉, M :N 관계가 된다는 것을 알 수 있다.
  • M : N 관계를 해결하기 위해서는 우린 새로운 주문 테이블을 만들 필요가 있다.
  • 위의 그림과 같이 주문 테이블 따로 만들 경우,
  • 서로의 1 : N 관계는 유지하면서 불필요한 중복 문제는 해결 할 수 있다.

2. DB 테이블의 방향성

  • 방향성이란?
    - 단반향일 경우는 유저 테이블에서만 음식 테이블을 참조 할 수 있어야하고, 음식 테이블에서만 유저 테이블을 참조 할 수 있어야한다.
    - 양방향일 경우는 서로 참조가 가능 할 수 있어야한다.
  • DB 테이블을 방향성이 존재 할까?
    - 위의 테이블들을 이용해서 아래의 쿼리를 이용하면 , 우린 고객 'Robbie'가 주문한 음식 정보를 고객 테이블 기준으로 조회가 가능하다.
     	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;
    - 그리고 아래의 쿼리를 이용하면, 음식 테이블 기준으로도 'Robbie'가 주문한 음식 정보도 조회가 가능하다.
        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 테이블들 간에는 방향성이 존재하지 않는다.

2. Entity간의 연관 관계

1. JPA Entity 에서의 테이블간의 연관 관계 표현

  • 음식 : 고객이 1 : N 관계일 경우, 즉 한명의 고객이 여러번 주문이 가능할 때, 아래의 코드와 같다.
@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 테이블 간의 연관 관계의 차이점은 DB에서는 배열을 허락하지 않지만, entity에서는 List<Food> foodList = new ArrayList<>() 와 같이 배열을 허락하기 때문에 우린 주문 테이블 없이도 1 : N 관계를 문제 없이 표현 할 수 있다.
  • DB 테이블에서는 join을 통해 고객 테이블 기준으로 음식 테이블을 조회가 가능하다. 하지만 entity같은 경우는 음식 필드값에 선언을 하지않으면 우린 고객 객체를 참조 할 수 없다. 즉, 선언을 함으로써 DB 테이블에 실제 컬럼으로 존재하지는 않지만 Entity 상태에서 다른 Entity를 참조할 수 있게 된다.

2. 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에서는 DB 테이블에는 없는 방향의 개념이 존재한다.
profile
밤낮없는개발자

0개의 댓글