당니의 개발자 스토리

실전 예제 4 - 상속관계 매핑 본문

스프링/자바 ORM 표준 JPA 프로그래밍 - 기본편

실전 예제 4 - 상속관계 매핑

clainy 2024. 8. 22. 21:45

실전 예제 4 - 상속관계 매핑

 

저희가 배운 상속관계 맵핑을 가지고, 실전에서 어떻게 쓰는지 실전 예제를 한번 보겠습니다.

저희가 했던 쇼핑몰에서 요구사항이 추가된 거예요. 상품의 종류는 음반, 도서, 영화가 있고 이후에 더 확장될 수 있다. 모든 데이터는 등록일과 수정일이 필수다. 이제는 무슨 말인지 알겠죠? 위에 말은 상속관계 맵핑을 쓰고, 아래 말은 @MappedSuperclass를 써야된다는 거겠죠.

그래서 도메인 모델을 보면 상품의 도서, 음반, 영화 이런 식으로 상속관계로 맵핑을 했구요.

이거를 보시면 기존 거에다가 Album, Book, Movie 한 다음에 상속관계로 만들었습니다. 자 이렇게 하고

테이블은 보시면 저는 싱글 테이블로 설계했습니다. 이제 어떻게 하면 되는지 한번 보겠습니다. jpashop2으로 돌아가서,

Album 클래스를 만들고요. 그 다음에 속성들을 넣어줄게요.

그 다음에 Getter, Setter를 만들고 extends Item 해줍니다.

Book도 마찬가지로 해주고,

마지막으로 Movie도 해줍니다.
자 이제 그 고민을 해야 돼요.

Item만 단독으로 테이블에 저장할 일이 있냐, 없냐를 판단을 해야 되는데 없다고 가정을 할게요.

그럼 추상 클래스로 만들고, 그 다음에 상속 이라고 딱 해주시고 전략을 잡아야 되는데 저는 싱글 테이블이니까 이렇게 딱 잡습니다. 이렇게 하면 끝납니다.

그리고 이제 뭐 @DiscriminatorColumn 이라고 적을 수 있어요. 기본이 DTYPE이니까 지우고,

이렇게 하면 끝납니다. 여기까지 하면

이대로 맵핑이 됩니다. 한번 돌려볼게요.

보시면 Item 테이블이 되게 커졌죠? 이렇게 해가지고 테이블이 쭉 생성된 것을 확인하실 수가 있습니다. 이제 값이 잘 들어가나 확인하기 위해서 Item을 한번 만들어봐야 되겠죠.
Item으로 생성하면 안되고, Book으로 생성해보겠습니다.

이렇게 세팅하고 나서, persist 한 다음에 돌려보면,

Item 테이블에 저장이 된게 나오죠. db에 가서

Select 쿼리를 날려보면, 데이터가 쫙 들어가있습니다. 나머지는 null로 들어가는 게 맞겠죠.

만약에 중간에 전략을 바꾸고 싶어. 싱글 테이블 말고 다른 거 할 거야 라고 하시면, 한번 JOINED로 바꿔 보겠습니다. 실행하면,

일단 이 테이블이 쭉쭉 생성이 되는데 먼저 Item 테이블이 좀 심플하게 생성이 됐구요.

그 다음에 Album, Movie, Book 다 생성이 되죠.

그리고 조인 전략에서는 이게 중요하죠.

아무래도 ITEM_ID를 같이 써야죠.
이제 db에 가서, refresh를 해보면

테이블들이 추가됐습니다. 쿼리를 날려보면 잘 들어가있습니다. Album에는 뭐가 없으니까 들어간 게 없겠죠. 이렇게 깔끔하게 나옵니다.

전략만 바꿔서 된거죠.

그 다음에 쓰면 안되는 TABLE_PER_CLASS까지 해보고 실행해보겠습니다.

TABLE_PER_CLASS를 하면 ITEM 테이블이 생성이 안돼요. 보시면 create table에서 Item이 없어요. Item이 없고 구체적인 테이블 Book으로 바로 나오겠죠.

그러면 제가 book table query 해보면 book 테이블에 그냥 값이 쫙 들어가 있죠. 여기 name, price, stock, quantity까지 다 들어가 있죠.

하지만 일단 결론적으로 여기서는 싱글 테이블을 선택했기 때문에 싱글 테이블로 해서 맞추면

이렇게 설계가 됩니다.

 

자 고급 맵핑상속 관계도 알아봤구요. 그 다음에 BaseEntity를 하나 만들어야 되겠네요. 이거는 이전 시간에 만든 걸 복사하겠습니다.

붙여놓은 다음에 이거를 쭉쭉쭉 받으면 되겠죠.

Item도 BaseEntity를 받고, 나머지 Member랑 Order, OrderItem, Category, Delivery에도 모든 테이블에 다 넣어줍니다.

Album에는 넣어줄 필요가 없죠. 상속관계가 지금 쭉쭉 올라가니까 Album은 Item을, Item은 BaseEntity를 가져가니까 필요가 없습니다. 이 정도만 해가지고 한번 실행해 볼게요.

create Table 문이 lastModifiedBy 이런 게 다 들어가죠. 모든 테이블에 다 들어갑니다.

그런데 여기에는 안 들어가죠. 그러니까 이 중간 테이블, 다대다 맵핑인데 그래서 @ManyToMany를 쓰면 안 된다는 거에요.
이제 db에 가셔서 Select 쿼리를 날려보시면,

Item 테이블에 속성이 들어가겠죠. BaseEntity 속성에는 값을 넣어주지 않았으니까 null인 거고, 넣으면 이제 값이 들어가겠죠. JPA에서는 이벤트 이런 게 있어가지고, 뭐 '영속하기 직전에 이런 걸 호출해!' 이런게 다 돼요. 그래서 사실 이 4가지 값은 다 자동으로 채울 수 있습니다. 나중에 스프링이랑 스프링 데이터 jpa 같은 거를 다 합쳐가지고 쓰면 가능합니다.

그러면 이 기능이 확장된 것, 도서, 음반, 영화를 확장을 했고,

이것들이 들어갔고요,

테이블 설계까지 들어갔습니다.


자 그럼 이제 그 실전 예제니까 실무에서 이렇게 쓰느냐? 좀 고민을 해보셔야 돼요. 이렇게 실전에서 상속관계를 써서 얻을 수 있는 이점단점이 있거든요. 뭐냐면,


노가다를 좀 하더라도 그냥 Item에 많이 때려받고 뭐 예를 들어서 크게 중요하지 않으면 Album, Book, Movie 이런 거를 JSON으로 말아넣고 쓰거나 하는 선택이 복잡도를 관리한다는 측면에서 더 나은 선택일 수도 있어요. 이게 또 데이터가 너무 많아져도 이렇게 고민이 됩니다.


JSON으로 말아넣는 다는게 무슨 의미인가요?

 


 

그래서 저도 이제 하면서 어떤 경우는 이렇게 해서 진짜 상속관계로 쓰는 경우도 있고요. 어떤 경우는 상속관계로 쓰다가 보니까, 이것도 너무 복잡한 거예요. 애플리케이션이 사용자도 많지 않고 그럴 때는 이런 상속관계나 이런 게 잘 동작하거든요. 그런데 데이터가 억단위가 넘어가고 파티셔닝 해야 되고 그런 상황까지 들어가기 시작하면 복잡해요. 하루에 100만 컷씩 쌓이고 이러면 고민거리가 확 늘어나거든요. 그러면 테이블을 단순하게 유지해야 돼요. 그래서 그런 경우에는 그냥 이런 Album, Book, Movie 같은 것들은 JSON으로 말아넣자 해서 말아넣는 경우도 있고 이게 딱 정답이 없는 것 같아요.
그런데 우선은 처음부터 모든 애플리케이션이 그렇게 크지 않잖아요. 그래서 이렇게 상속관계를 써서, 먼저 객체 지향적으로 설계해서 가다가 장점과 단점을 트레이드 오프가 넘어서는 시점에 시스템을 대비하면 되겠죠.

여기까지 설명드렸구요. 고급 맵핑과 상속 관계 맵핑은 마치겠습니다.

'스프링 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글

Mapped Superclass - 매핑 정보 상속  (0) 2024.08.22
실전 예제 3 - 다양한 연관관계 매핑  (0) 2024.07.17
다대다 [N:M]  (0) 2024.07.14
일대일 [1:1]  (0) 2024.07.07
일대다 [1:N]  (0) 2024.06.23