실전! 스프링 부트와 JPA 활용1(웹 애플리케이션 개발)

Ch02. 도메인 분석 설계 - 엔티티 클래스 개발

webmaster 2021. 12. 3. 12:05
728x90

예제에서는 설명을 쉽게 하기 위해 엔티티 클래스에 Getter, Setter를 모두 열고, 최대한 단순하게 설계

실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하는 것을 추천

참고

  • 이론적으로 Getter, Setter 모두 제공하지 않고, 꼭 필요한 별도의 메서드를 제공하는 게 가장 이상적이다. 하지만 실무에서 엔티티의 데이터는 조회할 일이 너무 많으므로, Getter의 경우 모두 열어두는 것이 편리하다. Getter는 아무리 호출해도 호출하는 것 만으로 어떤 일이 발생하지는 않는다. 하지만 Setter는 문제가 다르다. Setter를 호출하면 데이터가 변한다. Setter를 막 열어두면 가까운 미래에 엔티티에 가 도대 체 왜 변경되는지 추적하기 점점 힘들어진다.
  • 그래서 엔티티를 변경할 때는 Setter 대신에 변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 별도로 제공해야 한다.

엔티티 개발하기

Member Entity

Member Entity

Embeded Address

Embeded 타입 Entity(값 타입)

Order Entity

Order Entity

  • Member와 Order는 양방향 연관관계이기 때문에 엔티티에 각자 참조되는 부분이 있다
  • 단, 데이터 베이스에는 외래 키가 하나의 테이블에만 있기 때문에 둘 중 하나를 연관관계의  주인으로 설정하여 해당 테이블에 값이 변경되었을 때 참조된 값을 변경하도록 한다.
  • 따라서 DB에 FK가 존재하는 Order를 연관관계의 주인으로 설정한다(다인 쪽을 연관관계의 주인으로 설정하면 성능상 이슈와 유지보수가 간편하다)
  • Enum 타입같은 경우 @Enumerated를 해주어야 하는데 이때, default값이 ORDINAL인데 이는 숫자로 하나씩 증가하는 형태이다
    • ORDINAL 같은경우 중간에 값이 하나가 추가될 경우 참조되는 값이 변경되기 때문에 현업에서 사용 x
    • String을 사용하여 중간에 추가되어도 기존 값에 영향이 없도록 한다.

OrderItem Entity

OrderItem Entity

Item Entity

Item Entity

  • 상속관계로 만들어야 된다(DB에는 싱글 테이블 전략으로 들어갈 것이다)
  • InheritanceType 같은 경우 전략이 3가지 존재
    • Single_table : 하나의 테이블에 상속받은 모든 칼럼이 들어간다.
    • Table_per_class : 상속받는 엔티티들을 생성해준다(album, book, movie만 생성)
    • Joined : 가장 정규화된 스타일로 한다

자식 테이블

Album
Book
Movie

  • Album, Book, Movie 자식을 생성

Delivery Entity

Delivery Entity

  • OneToOne 같은 경우 연관관계의 주인을 많이 참조될 거 같은 곳에 지정해 주면 된다(여기서는 Order)

Category Entity

Category Entity

  • 계층 구조 같은 경우 자기 자신에게 외래 키를 걸어주면 된다.
  • 실무에서는 @ManyToMany 를 사용하지 말자
    • @ManyToMany는 편리한 것 같지만, 중간 테이블( CATEGORY_ITEM )에 칼럼을 추가할 수 없고, 세밀하게 쿼리를 실행하기 어렵기 때문에 실무에서 사용하기에는 한계가 있다. 중간 엔티티( CategoryItem를 만들고 @ManyToOne , @OneToMany로 매핑해서 사용하자. 정리하면 대 다대 매핑을 일대다, 다대일 매핑으로 풀어내서 사용하자
  • 엔티티의 식별자는 id를 사용하고 PK 칼럼명은 member_id를 사용했다. 엔티티는 타입(여기서는 Member )이 있으므로 id 필드만으로 쉽게 구분할 수 있다. 테이블은 타입이 없으므로 구분이 어렵다. 그리 고 테이블은 관례상 테이블명 + id를 많이 사용한다. 참고로 객체에서 id 대신에 memberId를 사용해도 된다. 중요한 것은 일관성이다

Embeded 설명

Embeded Type 설명( 값 타입)

  • 값 타입은 변경 불가능하게 설계해야 한다. 
  • @Setter 를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들자. JPA 스펙상 엔티 티나 임베디드 타입( @Embeddable )은 자바 기본 생성자(default constructor)를 public 또는 protected로 설정해야 한다. public으로 두는 것보다는 protected로 설정하는 것이 그나마 더 안전하다.
  • JPA가 이런 제약을 두는 이유는 JPA 구현 라이브러리가 객체를 생성할 때 리플랙션 같은 기술을 사용할 수 있도록 지원해야 하기 때문이다.
728x90