연관관계가 다양하게 연결되어 있는 엔티티의 경우 생성 메소드를 구현해서 엔티티를 만드는 것을 권장한다.
이러한 방식을 권장하는 가장 큰 이유는 바로 유지보수 때문이다.
먼저, 엔티티 한 개를 예로 들어보겠습니다.
@Entity
@Table(name = "orders")
@Getter
@Setter
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)//xtoOne 에 대한 지연로딩 설정
@JoinColumn(name = "member_id")//외래키 (조인키가 member_id 가 됨)
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL) //영속성 전이 설정 (All)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "delivery_id")
private Delivery delivery;//배송정보
private LocalDateTime orderDate; //주문 시간
@Enumerated(EnumType.STRING)// String Enum 설정
private OrderStatus status;
//연관관계 메소드
public void setMember(Member member){
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem){
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery){
this.delivery = delivery;
delivery.setOrder(this);
}
}
이렇게 Member 엔티티와 Delivery, OrderItem과 같이 다양한 엔티티와 연결되어 있는 경우 주문 엔티티를 생성하기 위해
회원, 배달, 주문 아이템 3가지 엔티티에 대한 생성자 호출도 같이 이뤄져야 합니다.
이 경우 주문 생성자 또는 관련 엔티티의 변경이 발생하면 생성 로직을 모두 찾아 함께 변경해줘야 되는 번거로움과 인재의 위험성이 높아지게 됩니다.
그래서 개발자는 생성 메소드를 통해 이런 유지보수의 어려움을 해결할 수 있습니다.
주문 엔티티에 대한 생성 메소드는 아래와 같이 구현할 수 있습니다.
//==생성 메소드==// 주문 엔티티처럼 연관된 관계가 다양하고 복잡한 경우 생성 메소드를 따로 구현함으로써 유지보수를 편리하게 한다.
public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){
Order order = new Order();
order.setMember(member);
order.setDelivery(delivery);
for (OrderItem orderItem: orderItems) {
order.addOrderItem(orderItem);
}
order.setStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
멤버, 배송과 주문 아이템을 생성자 매개변수를 전달받아 setter로 세팅해줍니다. 그러므로 생성 로직의 변경이 필요하면 해당 메소드만 수정됩니다.
하지만, 누군가 생성 메소드의 존재를 모르고 개별적으로 new Order(), new Member()..로 주문 정보를 생성할 수 있습니다.
이런 불균형 로직이 발생하지 않도록 @NoArgsConstructor어노테이션을 통해 제한할 수 있습니다.
JPA는 스택상 Protected까지 생성자를 허용해주기에 생성자 접근 권한을 protected로 변경함으로써 new Order()를 제한할 수 있다.
방법 1.
Protected Order Class 생성자를 만든다.
Ex) protected Order() {} 추가
방법 2.
Lombok를 사용해서 Protected 생성자 정의
클래스 상단에 @NoArgsConstrunctor(access = AccessLevel.PROTECTED)
'IT > Spring JPA' 카테고리의 다른 글
JPA 성능 최적화 (0) | 2021.08.13 |
---|---|
JPA 예외처리 및 프록시 심화 익히기 (0) | 2021.08.01 |
JPA 영속성 관리 (0) | 2021.07.15 |
JPA 웹 어플리케이션 개발 (0) | 2021.07.01 |
QueryDSL 사용법 (3) | 2020.02.17 |