[내일배움캠프 Spring 4기] 33일차 TIL - Entity 연관 관계

서예진·2024년 1월 31일
0

오늘의 학습 키워드 📕

▸ 코드카타
▸ Entity 연관 관계


▼ 코드 카타

2024년 1월 31일 - [프로그래머스] 17 : 문자열 나누기 | 대충 만든 자판 | 둘만의 암호


▼ Entity 연관 관계

📍 DB table간의 방향

  • DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있음 -> DB 테이블간의 관계에서는 방향의 개념이 없음

📍 JPA Entity에서 table간의 연관 관계

  • 음식 entity와 고객 entity가 있다고 가정

✔️ 1 대 1 관계 : @OneToOne

  • 단방향 관계
    • 음식 entity가 외래키의 주인인 경우(즉, 음식 entity가 고객 entity의 기본키를 외래키로 가지고 있는 경우)
[음식]
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToOne
    @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에는 @OneToOne, @JoinColumn이 있음

  • 양방향 관계
    • 외래키의 주인인 entity의 상대 entity에 mappedBy 옵션이 필요한다.
[음식]
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToOne
    @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;

    @OneToOne(mappedBy = "user")
    private Food food;
}

✔️ N 대 1 관계: @ManyToOne

  • 음식 entity와 고객 entity가 N 대 1의 관계이고 음식 entity가 외래키의 주인인 경우
  • 단방향 관계
    • 위의 코드의 음식 entity에서 @OneToOne -> @ManyToOne
  • 양방향 관계
    • 위의 코드의 음식 entity에서 @OneToOne -> @ManyToOne
    • 위의 코드의 고객 entity에서 @OneToOne -> @OneToMany

✔️ 1 대 N 관계: @OneToMany

  • 음식 entity와 고객 entity가 1 대 N의 관계이고 음식 entity가 외래키의 주인인 경우
  • 단방향 관계
    • 외래 키를 관리하는 주인은 음식 entity이지만 실제 외래 키는 고객 entity가 가지고 있음
    • 1 : N에서 N 관계의 테이블이 외래키를 가질 수 있기 때문에
    • 외래키는 고객 테이블에 외래 키 컬럼을 만들어 추가하지만 외래 키의 주인인 음식 entity를 통해서 관리함
    • 외래키를 음식 entity가 직접 가질 수 있다면 INSERT 발생 시 한번에 처리할 수 있지마 실제 DB에서 외래키를 고객 테이블이 가지고 있기 때문에 추가적인 UPDATE가 발생한다는 단점이 있음
[음식]
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @OneToMany
    @JoinColumn(name = "food_id") // users 테이블에 food_id 컬럼
    private List<User> userList = new ArrayList<>();
}

[고객]
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}
  • 양방향 관계
    • 1 대 N 관계에서는 일반적으로 양방향 관계가 존재하지 않음

✔️ N 대 M 관계: @ManyToMany

  • 음식 entity와 고객 entity가 N : M 관계이고 음식 entity가 외래키의 주인인 경우
  • N : M 관계를 풀어내기 위해서는 중간 테이블이 필요⭐️
    • 중간 테이블은 음식 entity의 기본키와 고객 entity의 기본키를 외래키로 가지고 있음
  • 단방향 관계
[음식]
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
    joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
    inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
}

[고객]
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}
  • 양방향 관계
[음식]
@Entity
@Table(name = "food")
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private double price;

    @ManyToMany
    @JoinTable(name = "orders", // 중간 테이블 생성
    joinColumns = @JoinColumn(name = "food_id"), // 현재 위치인 Food Entity 에서 중간 테이블로 조인할 컬럼 설정
    inverseJoinColumns = @JoinColumn(name = "user_id")) // 반대 위치인 User Entity 에서 중간 테이블로 조인할 컬럼 설정
    private List<User> userList = new ArrayList<>();
}

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

    @ManyToMany(mappedBy = "userList")
    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;

    @OneToMany(mappedBy = "food")
    private List<Order> orderList = new ArrayList<>();
}

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

    @OneToMany(mappedBy = "user")
    private List<Order> orderList = new ArrayList<>();
}

[주문]
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "food_id")
    private Food food;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}
profile
안녕하세요

0개의 댓글