당니의 개발자 스토리

엔티티 클래스 개발1 본문

스프링/실전! 스프링 부트와 JPA 활용1

엔티티 클래스 개발1

clainy 2024. 4. 17. 22:42

엔티티 클래스 개발1

안녕하세요 이번 시간에는 엔티티 클래스를 실제 코딩을 하면서 개발을 한번 해보겠습니다.

여기에 만들었던 회원 엔티티를 설계한 것을 실제 코드로, 라이브 코딩으로 녹이는 것을 보여드릴게요.

우선 참고적으로 예제에서는 최대한 설명을 쉽게 하기 위해서 엔티티 클래스에 Getter랑 Setter를 모두 다 열어둘 거에요. 그래서 최대한 단순하게 설계를 할 겁니다.

그런데 실무에서는 가급적이면 Getter는 열고 Setter는 꼭 필요한 경우에만 사용하시는 것을 추천드려요.

 

우선 하나 만들고 설명을 이어갈게요.

우선 여기다가도 domain이라는 패키지를 만들게요. 여기에 이제 핵심 엔티티들을 쭉 넣을 겁니다.

우선 먼저,

기존의 Member 클래스를 지우고 다시 할게요. domain 에다가 Member 클래스를 만듭니다.

먼저 @Entity 깔고, 그 다음에 id 변수를 만든 다음, @Id@GeneratedValue를 쓸 거예요. 그러면 이제 시퀀스 값 같은 걸 쓰겠죠.

그리고 name을 만들고, Address를 넣을 거거든요. 그런데 지금 Address가 없어서 만들어야 해요. option + enter 해서 클래스를 만듭시다.

일단 OK 해서 껍데기만 만들어둡시다.

그 다음에 이제 Member가 List로 orders를 가지기로 했었죠.

orders는 new ArrayList<>(); 이렇게 적어두시면 됩니다.

Order도 일단 껍데기만 만들어 놓겠습니다.

그러면 이제 회원은 거의 됐는데, 진짜 다 됐는지 한번 볼게요.

다 했네요. 이제 맵핑을 보겠습니다.

여기 보면 PKMEMBER_ID 거든요.

그래서 여기에다가 @Column(name = "member_id")을 줘야 됩니다. 이름을 이렇게 설정해줘야 우리가 만든 id 라는 변수명으로 안 되거든요. 그래서 컬럼명을 member_id로 줬습니다.

그 다음에 제가 롬복으로 Getter, Setter 열어준다고 그랬죠.

이렇게까지 하면 이제 완성이 됩니다.

 

그 다음에 Address로 가서,

이제 만들어봅시다.

Address에 city, street, zipcode 이렇게 넣기로 했었죠. 그리고 AddressJPA의 내장 타입이라는 것이기 때문에 @Embeddable 해주시면 됩니다. 그래서 어딘가 내장이 될 수 있다 라고 하고, 이제 얘도 Getter를 열어야 되겠네요. 여기까지 address까지 만들었구요.

그 다음에 address@Embedded 내장 타입을 포함했다. 라는 annotation으로 맵핑을 해주시면 됩니다. 이제 내장 타입을 쓸 때는 이거나 @Embedded나 @Embeddable 둘 중에 하나만 있으면 되거든요. 근데 그냥 두 개 다 많이 씁니다.

그래서 @Embeddable을 지워도 되긴 할 겁니다. 다시 원상복구 해줄게요.

@Embedded를 딱 보고 얘가 내장 타입이다, 아니다를 볼 수 있기 때문에 보통 둘 중 하나만 있어도 되는데, 저는 두 개 다 씁니다.

 

여기까지 하면 되고 그 다음에 Orders에 대한 것은 Order에 대해서 맵핑하고 나면 적어 볼게요.

그 다음에 Order를 만들어 보겠습니다.

Order는 우선 @Entity고 얘는 @Table을 적어 줘야 되죠. @Table(name = "orders") 라고 적어줍니다. 안 적으면 관례상 Order가 되어버리거든요. 그래서 orders로 바꾸겠습니다. 그리고 @Getter @Setter까지 만들고, 그 다음에 한번 봅시다.

이렇게 가지고 있네요. 이거를 쭉 코딩을 해보겠습니다.

DB column명을 order_id로 해줍니다. PK명이 ORDER_ID였기 때문이죠.

저는 원래 이 스타일을 더 선호해요. 이걸로 해도 되는데 보통 dba 분들이 이 방식을 선호하기 때문에 저도 그냥 거기에 잘 맞추는 편입니다. 그리고 이제 또 다른 이유가 있는데 그거는 뒤에서 설명을 드릴게요.

그 다음에 이제 Member와의 관계를 세팅해야 되죠. 지금 설명하는게 엄청 중요하겠죠. Order랑 Member다대일 관계란 말이에요.

그래서 @ManyToOne 입니다. Many가 Order죠.

자 반대로 Member의 입장에서의 List는 하나의 회원이 여러 개의 상품을 주문하기 때문에 일대다 관계가 됩니다.

자 그래서 서로 반대인거죠. @ManyToOne, @OneToMany 이렇게 연관관계를 적어주면 되고,

추가로 @JoinColumn(name = "member_id")을 적어서, 이제 외래 키 맵핑을 뭘로 할 거냐를 "member_id" 라고 이렇게 해주시면, 이 Foreign key 이름이 member_id가 된다고 보시면 됩니다.

절대 오해하시면 안되는 게, name 속성에다가 상대편 테이블 이름이 포함해야 된다고 생각하시면 절대 안됩니다.

여기를 예시로 들면, 그저 Order 테이블에 있는 member 라는 필드를 어떤 이름으로 컬럼명으로 설정할 것인지를 나타내주는 것 입니다.

그래서 @JoinColumn(name = "member_id") 라고 적었으면 그냥 Order 테이블에 member_id 라는 컬럼명이 정의되는 것이죠.

그러면, 이상한게 있습니다. 대체 Order 엔티티는 어떻게 Member 엔티티와 연관관계를 맺고 있다는 것을 알 수 있을까요?

Member 엔티티야 mappedBy 옵션으로 알려준다 하지만, Order 엔티티는 어떠한 설정도 하지 않은 것 같은데 말이죠.

바로, referencedColumnName 속성 때문이라고 알아두시면 됩니다. (참고 : https://boomrabbit.tistory.com/217)


JoinColumnEntity 연관관계 또는 Element Collection을 연결하기 위한 Column을 지정한다.

JoinColumn이 사용되는 용도는 주로, Entity의 연관관계에서 외래 키를 매핑하기 위해 사용된다.

JoinColumn의 name 속성 매핑할 외래 키의 이름을 지정하는 속성이다. 그냥 컬럼명을 설정한다고 생각하면 된다.


그러니까 정리하면, 지금 서로 연관관계를 가지는데 Order가 Member를 가지고 Member도 Order를 가지잖아요. 그런데 항상 다 쪽에 Foreign Key가 있으니까, Order에 있는 Membermember_id 라는 이름의 Foreign Key로 지정하는 거죠.

이렇게 해서 이제 주문한 회원에 대한 정보를 맵핑을 했습니다.

자 근데 이게 양방향 연관관계란 말이에요.

그러면 뭘 해줘야 되냐면 엄청 중요한 걸 해줘야 됩니다. 전에 말씀드린 연관관계 주인을 정해줘야 돼요.

지금 보면 Order의 회원을 바꿀 때,

여기에 값을 바꿀 수도 있고,

반대로 Member에서 OrderList의 값을 바꿀 수도 있단 말이에요. 둘 다 바꿔버리면 '도대체 JPA는 둘 중에 뭘 보고 확인을 해야 되지?' 혼란스럽거든요.

왜냐하면 Foreign key는 하나란 말이에요.

그래서 테이블을 보여드려야 되겠네요. 정리하는 차원에서 다시 말씀드릴게요.

Member는 orders를 List로 가지고 있어요. Order도 Member를 가지고 있단 말이에요. 지금 양방향 참조가 일어난 거에요.

그런데 문제는 뭐냐면,

데이터베이스에 Foreign Key는 MEMBER_ID, ORDERS에 있는 MEMBER_ID 하나밖에 없어요.

그래서 문제는 뭐냐면, Member와 Order의 관계를 뭔가 바꾸고 싶으면 사실 Foreign Key에 있는 값을 변경해야 되잖아요.

그러면 여기서 Member에도 Order와 관련된 연관관계를 하는 orders 라는 컬렉션 필드가 있는 거고, 반대로 Order에도 member라는 필드가 있단 말이에요. 그러면 둘 중에 'JPA에서는 둘 다 값을 확인을 해서 Foreign Key를 바꿔야 되나?' 이런 혼란이 오거든요.

'도대체 어디(Member or Order) 값이 변경됐을 때 저 Foreign Key를 바꿔야 되지?'

지금 Foreign Key를 바꾸는 기준에 대해서 얘기하고 있는 거예요.

예를 들어서 극단적으로 여기 Order에 있는 member에는 값을 세팅을 했는데 Member에 있는 orders에는 값을 세팅을 안 하거나, 아니면 orders에는 막 Order를 집어 넣는데, 반대로 이 Order 엔티티의 member에는 아무것도 안 넣은 거예요.

그러면 'JPA는 둘 중에 뭘 믿고 해야 되지?' 혼돈이 온단 말이에요.

'도대체 둘 중에 어떤 걸 뭘 믿고 저 Foreign Key 값을 업데이트를 쳐야 되지?'

왜냐면 Member와 Order의 관계에 대해 변경이 생기면, Foreign Key 값을 바꿔야 되니까요.

 

그래서 여기서 이제 Foreign Key 값을 업데이트를 치는 거는 둘 중에 하나만 선택을 하게 JPA에서 약속을 했어요.

왜냐하면 객체는 변경 포인트가 지금 두 군데(Member.orders와 Order.member)인데, 테이블은 Foreign Key 하나(ORDERS.MEMBER_ID)만 변경하면 된단 말이에요. 그래서 이거를 쉽게 맞춘 거예요.

그래서 이제 둘 중에 하나를 "주인"이라는 개념으로 잡는 거고, 여기서는 그게 연관관계의 주인입니다.

그래서 여러분이 orders나 member 중에 어떤 것의 값이 변경이 됐을 때 저 Foreign Key를 바꿀 건지 지정해 주면 되는데, 그게 연관관계의 주인입니다.

그래서 연관관계의 주인은 누구를 하면 되냐면 Foreign Key와 가까운 곳으로 하면 됩니다.

ORDERS를 보면 테이블에 지금 MEMBER_ID 라는 Foreign Key가 있죠. 얘를 연관관계의 주인이 있는 곳으로 맵핑하면 됩니다.

지금 엔티티를 보면,

orders랑 member 중에 자 이 Order에 있는 member가 더 Foreign Key가깝죠? 그럼 member를 연관관계의 주인으로 잡으시는 게 좋습니다.

안 그러면은 막 Member에 있는 뭔가를 바꿨는데, Order 테이블의 Foreign Key가 업데이트 되어버린단 말이에요. 그럼 관리하기가 어렵습니다.

'아 내가 분명 MEMBER를 바꾼 것 같은데 왜 ORDERS가 변경되지? 내가 안 건들인 테이블이 변경이 되네?' 이렇게 생각한다고요. 그래서 Order에 있는 member를 바꾸면, '아 내가 내 테이블에 있는 걸 바꾸니까 내 테이블에 있는 Foreign Key가 업데이트 되는구나' 하면서 머릿속에서 쉽게 흘러가거든요. 그리고 앞에서도 말씀드렸지만 뭔가 성능이나 이런 이슈들도 생길 수가 있습니다.

 

그래서 아무튼 복습 차원에서 다시 정리를 해드렸구요.

자 그래서 이제 얘를 연관관계의 주인으로 잡으면 되는데, 주인은 이대로 두면 되구요.

 

자 이제 반대로,

얘는 주인이 아니잖아요.

그래서 '나는 연관관계 거울이에요' 라는 의미로, mappedBy 라고 넣으시고, 지금 누구에 의해서 맵핑이 됐나요? Ordermember죠.

'Order 테이블에 있는 이 member 필드에 의해서 나는 맵핑 된 거야' 라는 의미로, mappedBy를 적는 순간, '나는 내가 맵핑을 하는 애가 아니고, 나는 member에 의해서 그냥 맵핑된 거울일 뿐이야' 라는 표현입니다. 그래서 여기는 이제 읽기 전용이 되는 거죠.

그래서 여기에 값을 뭔가 넣는다고 해서, Foreign Key 값이 변경되지 않아요.

자 그런데 여기에 값을 세팅하면, member_id 라는Foreign Key 값이 다른 member로 변경됩니다.

이제 여기까지 했고,

그림에 나머지 안 한 부분들을 채워넣읍시다.

일단 OrderItem이 없으니까 껍데기만 생성 해놓을게요.

Delivery도 껍데기만 생성 해놓겠습니다.

그리고 Java 8이니까 그냥 LocalDateTime을 쓰겠습니다. orderDate는 주문 시간인데 DateTime이니까 시간이랑 분까지 다 있는 거라고 보시면 됩니다. 뭐 orderDateTime이라고 해도 되는데 그냥 이렇게 쓰겠습니다.

 

그 다음에 enum 타입을 넣을 건데요.


Enum 클래스란?


OrderStatus 라는 걸 만들 거예요. 이게 뭐냐면 주문의 상태를 말하게 될 거고요. 저는 [ORDER, CANCEL] 이렇게 두 가지를 넣을 겁니다.

자 이제 enum 으로 OrderStatus을 만들게요.

그리고 얘는 ORDERCANCEL, 이렇게 두 가지 상태를 가지는 enum 입니다.

아직 이거는 없으니까 그냥 두고요.

여러분 예전에 JPA 공부하실 때 private Date 타입을 할 때는 Date를 쓰시면,

날짜 관련된 Annotation 맵핑을 해야 되거든요. 근데 Java 8에서는 LocalDateTime를 쓰면 Hibernate 알아서 자동으로 지원을 해줍니다. 그냥 쓰시면 돼요.

그래서 일단 이렇게 해놓고,

이 부분을 하나씩 세팅해볼게요.

가장 먼저 여기 OrderItem을 한번 세팅을 해보겠습니다. 그림부터 보여드릴게요.

자 OrderItem은 보시면,

Item을 가지고 있고 Order를 가지고 있고 주문가격과 카운트가 있습니다.

자 한번 해볼게요.

자 OrderItem은 당연히 @Entity 적고 getter, setter 넣어주고 @Id, @GeneratedValue 합니다. 그리고 Column명은 자동으로 나와야 되겠네요. 그래서 @Column(name = "order_item_id") 해주고, 변수 id를 잡은 다음에 Item을 적어야 되죠.

이렇게 한 다음에 Item이 일단 없어서 오류가 나니까 껍데기를 만들어줍니다.

그 다음에

orderPrice랑 count를 만드는데, orderPrice가 주문 당시의 어떤 가격입니다. 왜냐면 상품 가격은 바뀔 수가 있잖아요. 그리고 count는 주문 당시의 어떤 수량이라고 보시면 될 것 같아요.

자 그러면 Order랑 맵핑을 해볼께요. OrderItem과 Order다대일 관계죠. 그래서 @ManyToOne 적어주시고, 외래 키를 맵핑하기 위해서 @JoinColumn 넣어주셔야 겠죠. @JoinColumn(name = "order_id") 이렇게 합니다.

왜냐? 그림을 보시면,

하나의 Order가 여러 개의 OrderItem을 가질 수 있습니다. 반대로 OrderItem은 하나의 order만 가질 수 있게 되어있죠.

그러면 맵핑은 이제 어떻게 되냐면, Order에 orderItems가 있고 OrderItem에도 order가 있습니다. Member-Order 때와 똑같이 양방향 연관관계가 생겼죠.

자 그럼 테이블을 보겠습니다.

테이블은 당연히 다 쪽에 Foreign Key가 들어간단 말이에요. 지금 그래서 ORDER_ITEM에 ORDER_ID가 들어갔죠. 하나의 주문에 여러 개의 ORDER_ITEM이 들어가기 때문에 당연히 다에 Foregin Key가 들어온 겁니다.

자 그래서 이거를 맵핑하면 됩니다.

그럼 OrderItem에서 FK와 가까운 order가 연관관계의 주인이 되고, 맵핑을 쭉 하면 되겠죠.

그래서 보시면,

외래 키의 이름을 order_id@JoinColumn을 써서 외래 키를 맵핑해놨습니다. 그 다음에 Order 쪽, 그러니까 반대편 사이드도 해줘야 겠죠.

그런데 제가 엔터프라이즈 버전이기 때문에 JPA 세팅을

이렇게 Hibernate로 넣어주면,

이렇게 빨간불이 다 뜨죠. 이건 엔터프라이즈 버전만 될 거예요. 이렇게 빨간불 뜨는 것은 지금 맵핑이 없어서 그래요.

일단 이거는 @OneToMany(mappedBy = "order") 하면, '나는 연관관계의 거울인데, OrderItem에 있는 order 필드에 의해서 나는 맵핑 된 거야' 라는 의미입니다.

그러니까 OrderItem의 order에 의해서 맵핑이 된다는 겁니다.

그 다음에 이제 Item에 가보겠습니다.

Item은 일단 추상 클래스로 만들게요. 왜냐면 구현체를 가지고 할 거기 때문입니다.

자 일단은 @Entity를 하고 Getter랑 Setter도 만들겠습니다. 그 다음에 컬럼명을 item_id로 바꿨죠.

이제 Item 엔티티를 봐볼게요.

지금 이거를 맵핑을 해야 되는데 이게 지금 상속관계로 되어 있단 말이에요. 상속관계 맵핑을 해야 됩니다.

상속관계 맵핑에 대한 것은 기본편에 있는 상속관계 맵핑부를 잘 참고를 해주시고요. 바로 코딩을 해볼게요.

우선 먼저 속성들을 적어줄게요.

이거는 공통 속성이잖아요. 근데 이제 Book 막 이런 것들을 만들어야 되잖아요.

자, 그러면 이제 Item을 상속할 애들을 만들어야 됩니다.

이런 식으로 Album, Movie를 똑같이 만들어줍니다.

지금 뭔가 어쨌든 Item 덩어리인데 지금 점점 양이 많아지면서 이제 한눈에 안 들어오죠. 이 때 패키지를 만드는 겁니다.

item 이라는 패키지를 만들어서, 여기에다 몰아버릴 거에요.

얘네를

Refactor 눌러서,

이동을 해버리겠습니다.

이렇게 하고 Book 같은 경우,

일단 먼저 extends Item 해야겠죠. 상속이니까. 다른 애들도 extends Item 붙여넣기 해줍시다.

자 이제 Book은

이렇게 하면 되겠죠. 그리고 Movie는

이렇게 있고, Album은

이렇게 있습니다. 그리고 기본적인 getter, setter를 다 깔게요.

 

그 다음에 이제 상속관계 맵핑이기 때문에 중요한 걸 해야 됩니다. 뭐냐면 저희가 상속관계 전략을 지정해야 되는데, 이 전략을 부모 클래스에 적어주셔야 돼요. 즉, Item 클래스에다가 적어야 되는 거죠.

저희는 싱글 테이블 전략을 쓰니까 @Inheritance 해서 strategy 전략을 잡아야 하는데, 이 InheritanceType이 뭐가 있냐면,

SINGLE_TABLE, TABLE_PER_CLASS, JOINED 라고 있습니다.

이제 JOINED는 가장 정교화된 스타일로 하는 거고, SINGLE_TABLE은 한 테이블에 다 때려박는 거고, TABLE_PER_CLASS는 예를 들면 Book, Moovie, Album 이렇게 3개의 테이블만 나오는 전략입니다.

저희는 지난 시간에 말씀드렸듯이 싱글 테이블 전략을 선택할 거에요.

이렇게 해서 한 테이블에 다 때려박을 겁니다. 나중에 테이블 만든 거 보시면, Generate 된 거 보시면 다 딱 저 모양으로 나올 거에요.

그 다음에 @DiscriminatorColumn(name = "dtype")을 여기 적어 주시는데 dtype이라고 하면, Book을 읽을 때 'Book 이면 어떻게 할 거야' 이렇게 나오는 건데요.

이제 Book으로 가서,

@DiscriminatorValue("B") 라고 적어줍니다. 그러니까 어쨌든 지금 싱글 테이블이잖아요.

그래서 뭔가를 저장해둘 때 DB 입장에서는 뭐가 Book인지, 뭐가 Album인지 등 구분할 수가 있어야 된단 말이에요. 그 때 이제 넣는 값인데, @DiscriminatorValue를 기본값으로 두면 Book으로 들어갈 건데, 그냥 이렇게 할 수 있다라는 걸 보여드리기 위해서 Album과 Movie에다가도 쭉쭉쭉 해볼게요.

 

이렇게 하면 상속관계 맵핑이 끝납니다.

이제 다시 OrderItem으로 돌아와서,

Item과의 관계가 다대일 관계잖아요.

그래서 이렇게 하시면 됩니다. 다대일 관계를 명시하고 @JoinColumn을 통해서 외래 키를 맵핑했죠. 여기서는 Item으로 가서 mappedBy 해줄 필요가 없죠. 왜죠?

단방향 관계잖아요. Item은 OrderItem을 갖고 있지 않아요. 따라서 이렇게만 해주면 끝납니다.

 

그 다음에 이제 배송을 해보겠습니다.

Delivery가 이제 Order랑 관계를 가지죠.

그래서

Order를 적어주고, 그 다음에 Address value type에 있는 걸 재활용하는 겁니다. 내장 타입이기 때문에 @Embedded 어노테이션을 써주시면 되는 거구요.


Embedded type 은 사용자가 직접 정의한 값 타입이다. 여기서 Embedded type을 사용하지 않으면,

집 주소에 관한 정보 city, street, zipcode 를 전부 정의해 줘야 되는데, 그러면 객체지향적이지 않고 응집력을 떨어뜨리는 원인이 된다.

때문에 Embedded type을 사용하여 코드를 좀 더 명확히 한 것이다.


그 다음에 DeliveryStatus를 만들 거고, 이 status는 크게 READY는 배송준비고, COMP는 배송이라고 보시면 됩니다. 얘도 enum 클래스라는 느낌이 오셨죠?

그래서 DeliveryStatus는 enum으로 만들게요.

이렇게 만들었습니다.

자 이제 enum 타입은 조심하셔야 될 게 제가 엄청 강조했는데 먼저, @Enumerated Annotation을 넣으셔야 되고,

EnumType을 넣을 때 ORDINAL이랑 STRING을 넣을 수 있거든요.

EnumType의 DefaultORDINAL이에요. ORDINAL은 뭐냐면 0 1 2 3 4 이렇게 컬럼이 숫자로 들어가요.

예를 들어서 READY면 0이 들어가고 COMP면 1가 들어가고 이렇게 들어갈 거에요. 이런 식으로 숫자로 들어가는데, 이렇게 하면 문제가 있습니다. 

이런 식으로 중간에 어떠한 다른 상태가 생기면 망하는거죠. COMP가 원래는 1였는데 새로운 상태가 생기면서 2로 밀린 거잖아요.

DB 1을 조회하면 다 xxx로 나와요. 그래서 ORDINAL을 절대 쓰시면 안되고 DeliveryStatus는 꼭 STRING으로 쓰셔야 돼요.

그래야 READY와 COMP 중간에 뭐가 들어가도 순서에 의해서 밀리는게 없어요.

아까 OrderState도 Enum으로 만들었는데 안 해줬으니까

적어줍시다.

자 이제 Delivery랑 Order를 한번 맵핑을 해야 되겠네요. 얘네는 일대일 맵핑이란 말이에요.

@OneToOne을 적어주시고,

Order에서도 @OneToOne이죠.

하나의 주문은 꼭 하나의 배송 정보만 가져야 되고, 하나의 배송 정보도 꼭 하나의 주문 정보만 가져야 돼요. 이렇게 됐을 때가 일대일 관계가 성립하는데요.

JPA에서는 일대일 관계Foreign Key를 Order에 둬도 되고 Delivery에 둬도 되거든요. 어디에 두냐에 따라 다 장단점이 있어요.

제가 좀 선호하는 스타일은 주로 액세스를 많이 하는 곳에서 둬요.

Delivery를 직접 조회하는 일보다 우리 시스템은 가정이 거의 항상 Order를 보면서 Delivery를 본다고 가정을 하거든요. 그래서 Delivery를 가지고 Order를 찾을 일은 거의 없고, 그렇게 되면 저는 주로 Foreign Key 자체를 Order에다가 놓습니다.

지금 일대일 관계인 경우를 설명드리는 거예요.

그래서 ORDERS에다가 DELIVERY_ID 라는 Foreign Key를 놓았습니다. 이 Foreign Key를 Delivery에 둬도 되고 Order에 둬도 돼요.

그런데 저는 ORDERS에다가 DELIVERY_ID를 두는 선택을 했기 때문에, 이제 연관관계 주인을 정해야 되겠죠.

자 Order에도 delivery가 있고 Delivery에도 order가 있단 말이에요. 양방향 연관관계이죠.

그러면 연관관계 주인을 Foreign Key랑 가까운 곳에 있는 Order.delivery를 연관관계 주인으로 잡아주시면 됩니다.

방금 말씀드린 일대일에 대한 내용은 기본편 일대일 쪽에서 자세히 설명드리니까 참고하시면 됩니다.

그럼 이제 Order가 연관관계의 주인임을 명시해야겠죠.

일단, 외래 키를 맵핑하고 Delivery는 연관관계의 거울이죠? 양방향 관계니까.

그래서 Delivery로 가서,

이렇게 적어주시면 됩니다. 여기까지 해주시면 연관관계 맵핑이 되서 정리가 쭉 됐습니다.

 

다음 시간에는 나머지 애들을 마저 만들어보겠습니다.

'스프링 > 실전! 스프링 부트와 JPA 활용1' 카테고리의 다른 글

엔티티 설계시 주의점  (0) 2024.04.24
엔티티 클래스 개발2  (0) 2024.04.19
도메인 모델과 테이블 설계  (0) 2024.04.15
요구사항 분석  (0) 2024.04.13
JPA와 DB 설정, 동작확인  (0) 2024.04.13