[Spring] Entity 관계

2023. 9. 2. 20:33·개발 ━━━━━/Spring(boot)
반응형

1 대 1 관계

단방향 관계

Entity에서 외래 키의 주인은 일반적으로 N(다)의 관계인 Entity 이지만 1 대 1 관계에서는 외래 키의 주인을 직접 지정.

 

외래 키 주인만이 외래 키를 등록, 수정, 삭제할 수 있으며, 
주인이 아닌 쪽은 오직 외래 키를 읽기만 가능

 

<음식 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
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

 

양방향 관계

외래 키의 주인은 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정을 해준다.

상대 Entity는 외래 키의 주인 Entity 타입의 필드를 가지면서 mappedBy 옵션을 사용하여 속성 값으로 외래 키의 주인 Entity에 선언된 @JoinColumn()으로 설정되고 있는 필드명을 넣어준다.

 

 

// 음식 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 가 주인인 경우
// 고객 Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

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

// "user" 필드는 주인 Entity 의 @JoinColumn 이름
외래 키의 주인 Entity에서 @JoinColumn() 애너테이션을 사용하지 않아도 default 옵션이 적용되기 때문에 생략 가능

 

N 대 1 관계

단방향 관계

 

// 음식 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 가 주인인 경우
// 고객 Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

 

양방향 관계

 

// 음식 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 가 주인인 경우
// 고객 Entity
@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<>();
}

 

1 대 N 관계

단방향 관계

외래 키를 관리하는 주인은 음식 Entity이지만 실제 외래 키는 고객 Entity가 가지고 있다.

1 : N에서 N 관계의 테이블이 외래 키를 가질 수 있기 때문에 외래 키는 N 관계인 users 테이블에 외래 키 컬럼을 만들어 추가하지만 외래 키의 주인인 음식 Entity를 통해 관리한다.
// 음식 Entity 가 주인인 경우
// 음식 Entity
@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 가 주인인 경우
// 고객 Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}

 

외래 키를 음식 Entity가 직접 가질 수 있다면 INSERT 발생 시 한번에 처리할 수 있지만 실제 DB에서 외래 키를 고객 테이블이 가지고 있기 때문에 추가적인 UPDATE가 발생된다는 단점이 존재.

 

양방향 관계

1 대 N 관계에서는 일반적으로 양방향 관계가 존재하지 않는다.

1 대 N 관계에서 양방향 관계를 맺으려면 음식 Entity를 외래 키의 주인으로 정해주기 위해 고객 Entity에서 mappedBy 옵션을 사용해야 하지만 @ManyToOne 애너테이션은 mappedBy 속성을 제공하지 않는데,

N 관계의 Entity인 고객 Entity에서 @JoinColum의 insertable 과 updatable 옵션을 false로 설정하여 양쪽으로 JOIN 설정을 하면 양방향처럼 설정할 수는 있다.

 

// 음식 Entity 가 주인인 경우
// 고객 Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

		@ManyToOne
		@JoinColumn(name = "food_id", insertable = false, updatable = false)
		private Food food;
}

 

N 대 M 관계

단방향 관계

N : M 관계를 풀어내기 위해 중간 테이블(orders)을 생성하여 사용한다.

 

 

// 음식 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 가 주인인 경우
// 고객 Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
}
생성되는 중간 테이블을 컨트롤하기 어렵기 때문에 추후에 중간 테이블의 변경이 발생할 경우 문제가 발생할 가능성이 있다.

 

양방향 관계

 

// 음식 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 가 주인인 경우
// 고객 Entity
@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에 @ManyToMany 로 음식 Entity를 연결하고 mappedBy 옵션을 설정하여 외래 키의 주인을 설정하면 양방향 관계 맺음이 가능합니다.

 

중간 테이블 생성

중간 테이블 orders를 직접 생성하여 관리하면 변경 발생 시 컨트롤하기 쉽기 때문에 확장성에 좋다.

 

// 중간 테이블이 주인인 경우
// 음식 Entity
@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
@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;
}

 

관련 Annotation
@OneToOne
@JoinColumn
@ManyToOne
@OneToMany
@ManyToMany
반응형

'개발 ━━━━━ > Spring(boot)' 카테고리의 다른 글

[Spring] Singleton, Prototype Scope Bean  (1) 2024.09.06
[Spring] 이전 데이터를 불러올때 stream문과 for문의 성능 차이 테스트 - 1  (0) 2023.11.18
[Spring] WebSocket 을 이용한 채팅 구현  (1) 2023.10.09
[Spring] Filter  (0) 2023.09.01
[Spring] 인증 방식 (쿠키-세션, JWT)  (0) 2023.08.30
'개발 ━━━━━/Spring(boot)' 카테고리의 다른 글
  • [Spring] 이전 데이터를 불러올때 stream문과 for문의 성능 차이 테스트 - 1
  • [Spring] WebSocket 을 이용한 채팅 구현
  • [Spring] Filter
  • [Spring] 인증 방식 (쿠키-세션, JWT)
GukJang
GukJang
•  ⌘ ⌥ •
    반응형
  • GukJang
    SPACE
    GukJang
  • 전체
    오늘
    어제
    • Blog (73)
      • 개발 ━━━━━ (68)
        • Java (14)
        • C++ (1)
        • HTML (1)
        • Spring(boot) (7)
        • Dev (9)
        • SQL (1)
        • CS (2)
        • Git (1)
        • Troubleshoot (14)
        • Algorithm (2)
        • Definition (1)
        • Dev Life (2)
        • TIL (7)
        • 항해 (6)
      • 공돌 ━━━━━ (4)
        • 플젝 (2)
        • 장비 (1)
        • 부품 (1)
      • 독서 ━━━━━ (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    micropython
    오픈소스 기여
    알고리즘
    EC2
    docker
    백준
    SpringBoot
    electron-builder
    마이크로파이썬
    spring
    github actions
    AWS
    사전 스터디
    자바
    CI CD
    docker volume
    항해99
    mysql
    Python
    Java
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
GukJang
[Spring] Entity 관계
상단으로

티스토리툴바