본문 바로가기

IT/Spring JPA

생성자 제한하기

반응형

연관관계가 다양하게 연결되어 있는 엔티티의 경우 생성 메소드를 구현해서 엔티티를 만드는 것을 권장한다.

 

이러한 방식을 권장하는 가장 큰 이유는 바로 유지보수 때문이다.

 

먼저, 엔티티 한 개를 예로 들어보겠습니다.

@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