목차
연관 관계
연관관계란 두 도메인(객체, 테이블) 이 서로 논리적인 의미를 갖고 양쪽을 참조하는 관계를 의미합니다.
DB에서 테이블들이 연관 관계를 맺는 방법과 객체 지향 프로그램인 자바에서 객체(Entity)들이 연관 관계를 맺는 방법에 차이가 있습니다.
이 차이를 해소하여 테이블을 객체로 다룰 수 있도록 해주는 기술이 ORM이며, 자바 진영의 ORM 기술 표준 명세가 JPA입니다.
- 주문 APP DB 테이블 설계
DB 테이블의 연관관계와 Entity 간의 연관관계의 차이점을 설명하기 위해 주문 애플리케이션의 DB 테이블 설계를 가정하였습니다.
- 고객 (users) 테이블
- 주문 (orders) 테이블
- 음식 (food) 테이블
- DB 테이블 간의 방향
DB 테이블 간의 방향에서 방향은 크게 단방향과 양방향을 떠올릴 수 있습니다.
예를 들어 단방향은 users 테이블에서만 food 테이블을 참조할 수 있을 때를 의미하며,
반대로 양방향은 users 테이블과 food 테이블이 서로를 참조할 수 있을 때를 의미합니다.
- users 테이블에서 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 u.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 u.id = 1;
- DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있습니다.
→ DB 테이블 간의 관계에서는 방향의 개념이 존재하지 않는다.
- Entity 간의 연관 관계 (양방향 연관관계)
그렇다면 JPA Entity에서는 이러한 테이블 간의 연관 관계를 어떻게 표현하고 있을까요?
Food : User = N : 1 의 관계를 Entity (Java class)로 표현하면 다음과 같습니다.
- Food Entity
@Entity
@Getter
@NoArgsConstructor
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;
public Food(String name, double price) {
this.name = name;
this.price = price;
}
}
- User Entity
@Entity
@Getter
@Table(name = "users")
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Food> foodList = new ArrayList<>();
public User(String name) {
this.name = name;
}
}
- 한명의 고객이 여러번의 주문을 할 수 있는 상황을 가정했습니다.
이를 Entity에서 표현하기 위해 List<Food> foodList = new ArrayList<>() 로 표현할 수 있습니다. - DB 테이블에서는 User나 Food 테이블 어느 것을 기준으로 음식의 정보를 조회하더라도 JOIN을 사용하여 바로 조회가 가능하지만 User Entity 입장에서는 Food Entity의 정보를 가지고 있지 않으면 음식의 정보를 조회할 수 없습니다.
이를 해소하기 위해 DB 테이블에는 컬럼으로 존재하지 않지만, Entity 상태에서 다른 Entity를 참조하기 위해 이러한 방법을 사용합니다. - 현재 User Entity와 Food Entity는 서로를 참조하고 있으며, 양방향 관계를 갖습니다.
- Entity 간의 연관 관계 (단방향 연관관계)
단방향 연관관계는 다음과 같이 표현할 수 있습니다.
- Food Entity
@Entity
@Getter
@NoArgsConstructor
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;
public Food(String name, double price) {
this.name = name;
this.price = price;
}
}
- User Entity
@Entity
@Getter
@Table(name = "users")
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public User(String name) {
this.name = name;
}
}
- Food Entity에서만 User Entity를 참조할 수 있으며, 이러한 관계를 단방향 관계라고 합니다.
- User Entity에서는 Food Entity의 정보가 없기 때문에 음식에 대한 정보를 조회할 수 없습니다.
정리하자면
DB 테이블에서는 연관관계를 FK(외래키)로 맺을 수 있고, Entity에서는 상대 Entity를 참조(객체주소)하여 연관관계를 맺을 수 있습니다.
따라서 Entity에서는 DB 테이블에는 없는 방향의 개념을 갖습니다.
'JPA' 카테고리의 다른 글
[JPA] 다대일 연관관계 (양방향) (0) | 2023.04.29 |
---|---|
[JPA] 일대일 연관관계 (양방향) (0) | 2023.04.29 |
[JPA] 다대일 연관관계 (단방향) (0) | 2023.04.29 |
[JPA] 일대일 연관관계 (단방향) (0) | 2023.04.28 |
[JPA] JPA 동작 이해하기 - 동작 원리와 영속성 컨텍스트 (0) | 2023.04.27 |
댓글