Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 프로세스 동기화
- jpa
- 웹개발
- 2단계 Page Table
- 메모리의 불연속적 할당
- Page Table의 구현
- CS
- Effective Access Time
- 알고리즘
- 코드스테이츠 백엔드 과정 39기
- springboot
- Shared Page
- 메모리 관리
- linux
- 프로세스 불연속 할당
- 운영체제
- 다단계 페이지 테이블
- spring
- 문제풀이
- Segmentation with Paging
- 프로세스 할당
- 스프링
- 자바 알고리즘
- 자바 문제풀이
- 웹 프로그래밍
- Allocation of Physical Memory
- 스프링부트
- Inverted Page Table
- annotation
- 리눅스
Archives
- Today
- Total
GrowMe
[JPA] 엔티티 간 연관관계 매핑 방법 본문
JPA 엔티티 간 연관관계 매핑 방법
# JPA 연관관계 정의 규칙
# 양방향 VS 단방향
# 연관관계의 주인
# 1 : N
# N : 1
# N : N
# 1 : 1
🎮JPA 기본 사용법이 궁금하다면 -> https://grow-myself.tistory.com/33
*JPA에서 가장 중요한 것
- 객체와 테이블이 어떻게 매핑되는지 이해하는 것이 JPA에서 가장 중요
- 왜냐하면 그것이, JPA의 목적인 객체 지향 프로그래밍과 데이터베이스 사이의 패러다임 불일치를
- 해결하는 열쇠이기 때문
- 특히, 객체와 테이블 간 매핑을 넘어 엔티티 간의 연관관계 매핑의 이해는 어려우므로 더욱 중요하다.
*연관 관계 정의 규칙
- 다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)
- 방향 : 단방향, 양방향 (객체 참조)
- 연관 관계의 주인 : 양방향일 시, 연관 관계를 관리하는 주체
* 단방향 연관 관계
- Member 클래스만 Order 객체를 참조할 수 있다. (Member 클래스 내, List<Order>를 통해 접근 가능)
- Order 클래스만 Member 클래스를 참조할 수 있다. (Order 클래스 내, Member 객체 존재)
-> 이처럼, 한쪽 클래스만 다른 쪽 클래스가 참조 가능한 관계 : 단방향 연관 관계
* 양방향 연관 관계
- Member : List<Order>를 통해 Order 객체 참조 가능
- Order : 선언된 Member 객체를 통해, Member 객체 참조 가능
-> 양쪽 모두 참조 가능한 관계 : 양방향 연관 관계
* 단방향 VS 양방향 선택 기준
- Member.getOrder() 참조가 필요 시, Member -> Order 단방향 참조
- Order.getMember() 참조가 필요 시, Order -> Member 단방향 참조
- 둘 다 필요하다? : 양방향 참조
*연관 관계의 주인
- 두 객체 (A, B)가 양방향 관계이면, 둘 중 관리 주체인 주인 객체를 지정해줘야 JPA가 혼동하지 않는다.
- 가령, 게시글(Post)의 게시판을 다른 게시판(Board)로 수정하려할 때, Post 객체에서 setBoard()로 수정할 지, Board 객체에서 getPosts() 등의 메서드를 통해 수정할 지, JPA가 헷갈릴 수 있다. 따라서 관리 주체를 정해
- JPA에게 알려주어야 한다.
*N : 1 단방향
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
}
- @ManyToOne : 다대일의 관계를 명시(N 쪽의 클래스에, 상대쪽 객체를 참조 가능한 필드에 선언한다)
- @JoinColumn(name = ) : 생성되는 외래키의 이름을 설정해준다. N:1 연관관계에서 @JoinColumn은 생략 가능
- 외래키 칼럼은 상대 쪽의 PK(기본키)로 설정되어 생성된다.
- (이는 @JoinColumn의 referencedColumnName 옵션을 통해 기본키가 아닌 컬럼으로 수정이 가능하며, 관련된 엔티티들에 Serializabled을 상속하여 구현해주어야 한다.)
*N : 1 양방향
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
@OneToMany(mappedBy = "board")
List<Post> posts = new ArrayList<>();
}
- @OneToMany : 양방향으로 만들기 위해, 상대쪽을 참조가능한 필드(List<Post> posts)에 이 어노테이션을 추가.
- mappedBy 속성 : 연관관계의 주인을 상대 쪽으로 지정한다. 관리의 주체가 상대편인 Post가 되며, 값은 상대 객체의 필드 중 자신을 참조하는 필드로 지정해준다.
*1 : N 단방향
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
@OneToMany
@JoinColumn(name = "POST_ID") //일대다 단방향은 @JoinColumn필수
List<Post> posts = new ArrayList<>();
}
- @JoinColumn : 1: N 연관관계에서는 이 어노테이션을 생략하면, 자동으로 두 테이블을 연결해주는 중간 테이블을 생성하기 때문에, 비생산적이므로 꼭추가해줍니다.
*1 : 1 단방향
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@OneToOne
@JoinColumn(name = "ATTACH_ID")
private Attach attach;
}
@Entity
public class Attach {
@Id @GeneratedValue
@Column(name = "ATTACH_ID")
private Long id;
private String name;
}
- 주 테이블(Post)과 대상 테이블(Attach) 모두 외래키를 가질 수 있다.
- 게시글(Post)에 첨부파일(Attach)을 1개만 첨부할 수 있다고 가정
- @JoinColumn : Post 테이블에 외래키를 지정하여 Attach와 매핑합니다.
*1 : 1 양방향
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@OneToOne
@JoinColumn(name = "ATTACH_ID")
private Attach attach;
}
@Entity
public class Attach {
@Id @GeneratedValue
@Column(name = "ATTACH_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "attach")
private Post post;
}
- Attach 테이블에 @OneToOne 에너테이션을 추가하고, mappedBy로 주인이 Post임을 JPA에게 알려줍니다.
- 주 테이블에 외래키를 두는 것이 보통이지만, 상황마다 성능 차가 생길 수 있어, 대상 테이블에 외래키를 두는 경우도 있습니다.
*N : N 연관관계
- 중간 테이블을 하나 추가하여, 두 개의 다대일 관계를 만들어 준다.
- 중간 테이블은 각 테이블의 외래키를 가지고 있다.
- 각 다대일 관계는 :
- 다대일 매핑을 먼저 한 후, 참조가 추가로 필요하면, 일대다 매핑을 추가하여, 양방향으로 만들어준다.
@Getter
@Entity
@NoArgsConstructor
public class OrderCoffes {
@ManyToOne
@JoinColumn(name = "COFFEE_ID")
private Coffee coffee;
@ManyToOne
@JoinColumn(name = "ORDER_ID")
private Order order;
@Column(nullable = false)
private int quantity;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long orderCoffesId;
public void addCoffee(Coffee coffee) {this.coffee = coffee;}
public void addOrder(Order order) {this.order = order;}
}
@Getter
@Setter
@Entity(name = "ORDERS")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderId;
@Enumerated(EnumType.ORDINAL)
private OrderStatus orderStatus = OrderStatus.ORDER_REQUEST;
@Column(nullable = false)
private LocalDateTime createdAt = LocalDateTime.now();
@Column(nullable = false, name = "LAST_MODIFIED_AT")
private LocalDateTime modifiedAt = LocalDateTime.now();
@OneToMany(mappedBy = "order", cascade = CascadeType.PERSIST)
private List<OrderCoffes> orderCoffes = new ArrayList<>();
}
@NoArgsConstructor
@Getter
@Setter
@Entity
public class Coffee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long coffeeId;
@Column(length = 100, nullable = false)
private String korName;
@Column(length = 100, nullable = false)
private String engName;
@Column(length = 5, nullable = false)
private int price;
@Column(length = 3, nullable = false, unique = true)
private String coffeeCode;
@OneToMany(mappedBy = "coffee")
private List<OrderCoffes> orderCoffes = new ArrayList<>();
}
- OrderCoffes : N : N 매핑을 위해 추가한 중간 테이블. Order 테이블과, Coffee 테이블의 외래키를 가지고 있다.
- mappedBy : OrderCoffes 객체가 Order와 Coffee 클래스의 연관관계 주인임을 나타내고 있다.
- cascade = CascadeType.PERSIST : 객체가 영속화될 때, 연관된 객체도 함께 영속화 시킨다. 여러가지 옵션이 있지만, 스압이 걱정되므로... cascade에 대한 자세한 설명은 추후에 포스팅하도록 하겠다...
'About Spring' 카테고리의 다른 글
[API 문서화] Spring Rest Docs를 통한 API 문서화 (0) | 2022.08.19 |
---|---|
[Spring] 이벤트를 처리하는 방법 (0) | 2022.07.12 |
SpringBoot에서 JPA 사용하기 (0) | 2022.06.30 |
[Spring] Mapper와 MapStruct에 대해 알아보자 (0) | 2022.06.28 |
[Spring] DTO의 개념과 그 활용 방법 (0) | 2022.06.27 |
Comments