엔티티 클래스 개발2(주의사항)

Mina Park·2022년 9월 18일
0

1. 엔티티에서는 가급적 Setter 사용 지양

  • 변경 포인트가 너무 많아져서 유지보수가 어려움

2. 모든 연관관계는 지연로딩(LAZY)으로 설정

  • 즉시로딩(EAGER)의 경우 예측이 어렵고 어떤 SQL이 실행될지 추적하기 어려움
  • 특히 JPQL 실행시 N+1 문제가 자주 발생
    • 📌 실무에서는 기본적으로 전부 LAZY로 설정
      • 연관된 엔티티를 함께 DB에서 조회해야할 경우에는 fetch join 이나 엔티티 그래프 기능 사용
      • @NToOne(OneToOne, ManyToOne)의 경우 기본 fetch 전략이 EAGER이므로 필수로 변경

3. 컬렉션은 필드에서 초기화

  • 첫번째 소스처럼 필드에서 바로 초기화하는 것이 안전, nullPointException 방지 가능
 @OneToMany(mappedBy = "member") //relation target
    private List<Order> orders = new ArrayList<>();
 public Member() {
 	orders = new ArrayList<>();
 }
  • 하이버네이트는 엔티티를 영속화할 때 컬렉션을 감싸서 하이버네이트가 제공하는 내장 컬렉션을 변경함(본인이 추적할 수 있도록)
    • 때문에 임의의 메소드에서 컬렉션을 변경하면 하이버네이트 매커니즘 오류 발생

4. 테이블, 컬럼명 생성 전략

  • 스프링 부트에서 하이버네이트 기본 매핑 전략을 변경해서 실제 테이블 필드명은 다름
    https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#howtoconfigure-hibernate-naming-strategy
    http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#naming

  • 스프링 부트 신규 설정 (엔티티(필드) 테이블(컬럼))
    1. 카멜 케이스 언더스코어(memberPoint memberpoint)
    2. .(점)
    (언더스코어)
    3. 대문자 소문자

  • 적용 2 단계
    1. 논리명 생성: 명시적으로 컬럼, 테이블명을 직접 적지 않으면 ImplicitNamingStrategy 사용
    spring.jpa.hibernate.naming.implicit-strategy : 테이블이나, 컬럼명을 명시하지 않을 때 논리명
    적용,
    2. 물리명 적용:
    spring.jpa.hibernate.naming.physical-strategy : 모든 논리명에 적용됨, 실제 테이블에 적용
    (username usernm 등으로 회사 룰로 바꿀 수 있음)

  • 스프링 부트 기본 설정

    • spring.jpa.hibernate.naming.implicit-strategy:
      org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
    • spring.jpa.hibernate.naming.physical-strategy:
      org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

4. cascade

  • 해당 엔티티와 생명주기를 같이 하게 됨
  • 원래는 엔티티별로 persist를 해야하지만 CascadeType.ALL인 경우는 persist가 전파되기 때문에 연관 엔티티까지 저장, 삭제 등이 한꺼번에 처리됨
 @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) //relation target
    private List<OrderItem> orderItems = new ArrayList<>();

5. 연관관계 편의 메소드

  • 양방향인 경우 데이터가 변경되면 주인/역방향 모두에 값을 세팅해줘야 하는데, 하나의 메소드로 양쪽을 모두 처리
  • 위치는 가급적 연관관계 주인쪽에 설정
    //연관관계 편의 메소드
    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);
    }

0개의 댓글