주문(order)엔티티클래스파일에서

실습

 

order_id

-DB컬럼의 id이름을 테이블명으로 가져와 테이블명_id형태로 설정해준다.

DBA포지션 엔지니어가 이러한 형태로 설정해주는 것을 원한다.

 

참고

엔티티의 식별자는 id를 사용하고 PK 컬럼명은 member_id를 사용했다. 엔티티는 타입(여기서는 Member)이 있으므로 id 필드만으로 쉽게 구분할 수 있다. 테이블은 타입이 없으므로 구분이 어렵다. 그리고 테이블은 관례상 테이블명 + id를 많이 사용한다. 참고로 객체에서 id 대신에 memberId를 사용해도 된다. 중요한 것은 일관성이다.

 

-@ManyToOne : 주문과 회원의 관계, 다대 1관계를 설정해주는 어노테이션

-@JoinColumn(name = "member_id")

*@JoinColumn 어노테이션은 외래 키를 매핑 할 때 사용

*name 속성에는 매핑 할 외래키(연관관계주인) 이름지정

-member_id = foregien key(외래키)

-주문회원테이블에서 주문회원에 대한 정보를 매핑

 

 

 

회원엔티티클래스(RealMember)에서

어노테이션 설정

-@OneToMany : 회원과 주문의 관계, 1대 다 관계를 설정해주는 어노테이션

-@OneToMany (mapped by = "member")

*foreign key가 있는 order클래스에 있는 member가 연관관계의 주인이다.

*mapped by - order 테이블에 있는 member필드에 의해 맵핑된 거울일 뿐이야라는 뜻

*여기에 무엇을 넣는다고 해서 order에 있는 member필드의 foreign key 값이 변경되지

 않는다.

*order엔티티클래스에 있는 order테이블에 있는 member필드 값을 변경하면

 member_idforeign key 값이 변경된다.

 

 

연관관계의 주인설정이 필요한 이유

연관관계 맵핑 분석을 다시 확인해보자

회원과 주문

-회원도 오더로 갈 수 있고, 오더도 회원으로 갈 수 있도록 설계 했다.(양방향 연관관계)

-일대다, 다대일의 양방향 관계다. 따라서 연관관계의 주인을 정해야 한다.

 관계형데이터베이스에서는 1대 다의 관계에서는 다에 무조건 외래키가 있게 된다.

 외래 키가 있는 주문을 연관관계의 주인으로 정하는 것이 좋다.

 

이유

-주문클래스에서 멤버값을 바꾸거나, 멤버클래스에서 오더값을 바꿀 수도 있기 때문에

 JPA는 혼란스러울 수 있다.

-회원엔티티로 본다면 Order도 멤버정보를 가지고 있고, Member도 주문정보를 가지고 있

 다. 데이터베이스에서 MemberOrder테이블에서 볼 때에 foreign keyOrder테이블에

 한 개 밖에 없는 상태이다.

-추후 일어날 수 있는 문제라고 한다면, 회원과 주문테이블 관계를 바꾸고 싶을 때 foreign

 key를 변경해야 하는 상황에 처하게 된다.

-Member테이블에도 orders라는 컬렉션 필드가 있는거고, Order테이블에도 member라는

 필드가 있어 JPA에서는 둘다 정보를 확인해서 값을 바꾸어야 하나라는 혼란에 빠진다.

 즉, 어디에 값이 바뀌었을 때 foreign key를 바꾸어야 하는지에 대한 혼란을 겪게 된다.

-극단적으로 Order엔티티에서는 member 값을 세팅했는데, Member엔티티에서 order 값을

 세팅 안한다던가, Member엔티티에서는 order값을 넣었는데, Order엔티티에서는 member

 값을 안넣었다던가 하는 경우가 생기면, JPA는 둘중에 무엇을 믿고 order테이블의 foreign

 key 값을 업데이트를 해야 하지?라고 혼란을 겪는다.

 

여기서 foreign keyupdate하게 하기 위해서 JPA에서 둘중에 하나를 선택하라고 약속을 했다. 엔티티에서의 객체는 변경 포인트가 두군데이지만, 테이블은 foreign key하나만 변경하면 되기 때문에, 쉽게 맞추기 위해 규칙을 정했다.

둘중에 하나를 주인이라는 개념으로 잡으면 되는데 이것이 연관관계의 주인이다.

Member엔티티에서 ordersOrder엔티티에서나 member중에 값이 바뀌었을 때에 foreign key를 바꿀 거야 라는 것을 결정을 하는 것이 연관관계의 주인이다.

 

그렇다면 연관관계의 주인은 누구로 하는가?

-foreign key가 가까운 테이블(Order)을 확인하고 Member_id를 연관관계주인이 있는 곳으

 로 맵핑을 하면 된다.

-Order엔티티의 member가 가까우니 여기를 연관관계주인으로 정한다.

-이렇게 하지 않으면 member의 무언가를 바꾸었는데, Order테이블에 무언가/foregin키가

 업데이트 되어버려서 있는 의도치 않은 일이 일어난다. 성능이슈가 생길 수도 있다.

 Member정보를 변경했는데, orders의 값이 바뀌지하고 헷갈리게 되어버린다.

-foreign key가 있는 Order테이블에 있는 member를 바꾸니까 order테이블에 있는 컬럼이

 바뀌는구나 하고 이해하기도 관리하기도 쉬워진다. 이렇게 규칙을 정하지 않으면 Member

 보를 변경했는데, orders의 값이 바뀌지하고 헷갈리게 된다.

들어가기에 앞서

-예제에서 쉽게 설명하기 위해서 엔티티클래스에 setter getter를 모두 열어두어

 단순하게 설계를 할 것이다.

-실무에서는 getter는 열고, setter는 꼭 필요할 때에만 사용하는 것을 추천한다.

 

1. 회원엔티티개발

 

실습

회원엔티티클래스 생성 및 작성

설명

회원엔티티개발

a. jpabook.jpashopPackagedomain이라고 만든다.

-여기에 핵심 엔티티들을 설치 할 것이다.

 

b. 회원엔티티 작성

-List, ArrayList import class를 해줌

 

c. Address, Order 클래스 파일 생성

 

c. 회원테이블 이름 매핑

-@Id, @generatedValue, @Columns 어노테이션 세팅

 

2.주소값 타입 개발

실습

주소값타입개발

설명

a. address주소 클래스에서 코드작성

@Embeddable 어노테이션 사용

-address 주소가 어딘가에 내장될 수 있게 하기 위해 사용

@Getter 어노테이션을 열어두기

 

b.회원엔티티(RealMember)클래스파일에서 내장타입관련 어노테이션 세팅

-Address변수에 내장타입을 포함했다라는 @Embedded 어노테이션으로 매핑을 해주었다.

-Address변수에 @Embedded 하나만 있어도 되지만,  대개 두가지 어노테이션을 많이 사용한다.

 

3. 주문(order)엔티티클래스파일에서

실습

주문엔티티클래스 생성 및 작성(주문과 회원관계 연관관계매핑)

설명

a.주문엔티티클래스파일에서

-@Entity, @Table 이름 설정을 했다.

-@Table(name = "orders")라고 해주지 않으면

  public class Order에서 Order의 관례로 이름이 Order가 되어 버리기 때문에 이름 설정을 해주어야 한다.

 

b.order_id

-DB컬럼의 id이름을 테이블명으로 가져와 테이블명_id형태로 설정해준다.

 DBA포지션 엔지니어가 이러한 형태로 설정해주는 것을 원한다.

 

참고

엔티티의 식별자는 id를 사용하고 PK 컬럼명은 member_id를 사용했다. 엔티티는 타입(여기서는 Member)이 있으므로 id 필드만으로 쉽게 구분할 수 있다. 테이블은 타입이 없으므로 구분이 어렵다.

그리고 테이블은 관례상 테이블명 + id를 많이 사용한다.

참고로 객체에서 id 대신에 memberId를 사용해도 된다. 중요한 것은 일관성이다.

 

c.@ManyToOne

-주문과 회원의 관계, 다대 1관계를 설정해주는 어노테이션

 

d.@JoinColumn(name = "member_id")

-@JoinColumn 어노테이션은 외래 키를 매핑 할 때 사용

 

e.name 속성에는 매핑 할 외래키(연관관계주인) 이름지정

-member_id = foregien key(외래키)

-주문회원테이블에서 주문회원에 대한 정보를 매핑

 

 

4. 회원엔티티클래스(RealMember)에서

실습

회원엔티티 연관관계 매핑

 

a.어노테이션 설정

@OneToMany

-회원과 주문의 관계, 1대 다 관계를 설정해주는 어노테이션

 

@OneToMany (mapped by = "member")

-foreign key가 있는 order클래스에 있는 member가 연관관계의 주인이다.

-mapped by - order 테이블에 있는 member필드에 의해 맵핑된 거울일 뿐이야라는 뜻

-여기에 무엇을 넣는다고 해서 order에 있는 member필드의 foreign key 값이 변경되지

 않는다.

-order엔티티클래스에 있는 order테이블에 있는 member필드 값을 변경하면

 member_idforeign key 값이 변경된다.

 

어노테이션 설명 참고

https://docs.oracle.com/javaee/6/api/index.html

어노테이션이 궁금하다면 java.persistence -> annotation type을 클릭하면 어노테이션 설명을 볼 수 있다.

 

1.4 연관관계 맵핑 분석

회원과 주문

-회원도 오더로 갈 수 있고, 오더도 회원으로 갈 수 있도록 설계 했다.(양방향 연관관계)

-일대다 , 다대일의 양방향 관계다. 따라서 연관관계의 주인을 정해야 한다.

 관계형데이터베이스에서는 1대 다의 관계에서는 다에 무조건 외래키가 있게 된다.

 외래 키가 있는 주문을 연관관계의 주인으로 정하는 것이 좋다.

 그러므로 ORDERS 엔티티에 있는 MEMBER가 연관관계의 주인이 되고,

 MEMBER엔티티의 ordersmapped by로 단순 읽기만 가능한 연관관계의 거울 즉 단순

 조회용으로만 이용한다.

-연관관계의 주인쪽에 값을 세팅해야 값이 변경된다.

 거울쪽값은 단순조회용이다.

 

-일대다, 다대일의 양방향 관계다. 따라서 연관관계의 주인을 정해야 하는데,

 외래 키가 있는 주문을 연관관계의 주인으로 정하는 것이 좋다.

 그러므로 Order.memberORDERS.MEMBER_ID 외래 키와 매핑한다.

 

*쉽게 얘기하면 주문이 한 개만 있는 것이 아니라 많아질 수 있다고 할 때에

주문쪽에서 PK생성으로 멤버를 참조하여야 하므로 1(MEMBER) (ORDERS)의 관계라고

할 수 있다. 주문측이 갑, 주인이 된다.

 

주문상품과 주문

-한번 주문할 때 주문수량과 주문수량에 따라 가격이 달라질 수 있기 때문에

 주문상품을 두게 된다.

-다른 사람이 주문한 정보가 주문상품에 있을 수 없다.

 주문한상품들이(OrderItem)에는 주문할 때 하나의 Order에만 연관관계가 걸린다.

 주문상품들의 정보들이 OrderItem : List에 오게 된다.

 그래서 다대(ORDERS_ITEM)1(ORDERS)관계가 된다.

 

->다대일 양방향 관계다. 외래 키가 주문상품에 있으므로 주문상품이 연관관계의 주인이다.

   그러므로 OrderItem.orderORDER_ITEM.ORDER_ID 외래 키와 매핑한다.

 

*연관관계 매핑 분석할 때에

-서비스의 특성과 일반적인 관계를 알고, 일반적으로 접근해볼 것

-외래키가 있는 곳이 연관관계의 주인

 

주문상품과 상품

-itemorderitem에서 의 정보를 맵핑 할 것이 없다.

-나를 주문한 orderitem을 찾아 할필요가 없고,

 orderitem을 찾고 싶을 때에 루트를 orderitem으로 쿼리를 찍으면 된다.

 즉, orderitem에서 item정보만 잘 맵핑해주면 된다.

->다대일 단방향 관계다. OrderItem.itemORDER_ITEM.ITEM_ID 외래 키와 매핑한다.

   주문과 배송

-일대일 양방향 관계다. Order.deliveryORDERS.DELIVERY_ID 외래 키와 매핑한다.

-주문정보에 배송정보가 들어가고 OrdersDelivery_ID(PK)가 넣어 두었다.

 

-DELIVERY_ID가 있는 외래키와 매핑하면 Orders가 연관관계의 주인이 된다.

 

카테고리와 상품

-@ManyToMany를 사용해서 매핑한다.

 (실무에서 @ManyToMany는 사용하지 말자. 여기서는 다대다 관계를 예제로 보여주기 위

 해 추가했을 뿐이다)

-편법이 아닌 정상적인 방법으로는 테이블관계는 ManyToMany로 표현할 수 있는 방법이

 없기 때문에, CATEGORY_ITEM 중간테이블로 풀어낸다..

 

카테고리와 상품관련하여 앞에서의 내용과 같은 내용

-객체에서는 카테고리가 아이템리스트를 가져도 되고

 아이템이 카테고리리스트를 가져도 된다.

 양쪽 컬렉션을 만들면 객체는 다대 다로 만들 수 있지만

 관계형데이터베이스는 일반적 설계로는 그렇게 할 수 없다.

 중간에 매핑 테이블(CATEGORY_ITEM)을 두어,

1(CATEGORY) (CATEGORY_ITEM) 관계 및 다대(CATEGORY_ITEM) 1(ITEM)로 풀어

낸다.

 

참고

-외래 키가 있는 곳을 연관관계의 주인으로 정해라.

 연관관계의 주인은 단순히 외래 키를 누가 관리하냐의 문제이지 비즈니스상 우위에 있다고

 주인으로 정하면 안된다..

-예를 들어서 자동차와 바퀴가 있으면, 일대다 관계에서 항상 다쪽에 외래 키가 있으므로

 외래 키가 있는 바퀴를 연관관계의 주인으로 정하면 된다.

 

주의 (연관관계를 잘못 설정하게 되면 생기는 현상)

-물론 자동차를 연관관계의 주인으로 정하는 것이 불가능 한 것은 아니지만,

 자동차를 연관관계의 주인으로 정하면 자동차가 관리하지 않는 바퀴 테이블의 외래 키 값이

 업데이트 되므로 관리와 유지보수가 어렵고, 추가적으로 별도의 업데이트 쿼리가 발생하는

 성능 문제도 있다. 자세한 내용은 JPA 기본편을 참고하자.

 

+ Recent posts