이게 테이블 구조고,
객체도 이거와 별반 차이가 없었다.
우선은 단방향부터 잘 매핑하고, 그 후 필요하면 양방향 하겠다.
먼저, Member
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
}
바뀐 것은 없다.
그 다음 Order.
얘는 이제 외래키에서 참조로 바꿔야 한다. 그리고 다대일매핑이다.
@Entity
@Table(name="ORDERS")
public class Order {
@Id
@GeneratedValue
@Column(name="ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
}
다대일 매핑에,
Member join할 때 쓰는 열은 MEMBER_ID
Member Entity의 테이블에서 가져올 때 MEMBER_ID에 맞춰서 가져온다는 뜻 인거 같음.
(mapped by는 양방향 할 때 쓰는거다.)
Item 먼저,
@Entity
public class Item {
@Id
@GeneratedValue
@Column(name="ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
참조할 외래키(연관관계) 없다. 밖에서 얘를 참조하지.
OrderItem
@Entity
public class OrderItem {
@Id
@GeneratedValue
@Column(name="ORDER_ITEM_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "ITEM_ID")
private Item item;
@ManyToOne
@JoinColumn(name = "ORDER_ID")
private Order order;
private int orderPrice;
private int count;
}
2곳이나 참조한다.
Order와 Item
테이블 또한 ITEM_ID와 ORDER_ID라는 외래키를 가지고 있다.
가져온다.
Item은 Item 엔티티의 테이블에서 ORDER_ITEM 테이블이 가지고 있는 ITEM_ID와 맞춰서 가지고 오고,
마찬가지로 Order테이블인 ORDERS 테이블에서 ORDER_ITEM(자가자신)이 가지고 있는 ORDER_ID와 맞춰서 가지고 온다.
이제 양방향에 대해서 좀 고민을 해 보겠다.
양방향 설계는, 정말 필요에 따라 이루어 지는 것 이다.
일단 위에서 단방향 설계는 마쳤고,
이 양방향 설계도 하나의 예시일 뿐이다.
Member가 orders를 가지고 있는 등..
order가 orderItems를 가지고 있는 등..
이게 예시라서 이렇게 하긴 했는데,
Member가 orders를 객체로 가지고 있는 경우는 잘 없다고 한다.
보통 member의 id를 보고 다시 order에서 select 날려서 가져오지..
반면 Order가 orderItems를 가지고 있는 것은 충분히 납득이 간다.
보통 주문 정보 조회할 때 우리가 주문 날짜와 주문 상태도 (배송중 등) 확인을 하긴 하지만, 뭘 주문했는지 보는 경우, 주문한 상품에 대한 정보가 필요한 경우는 무수하다.
일단 객체상에 양방향 연관관계를 추가해 보자. (테이블상에는 사실 양방향 연관관계는 없다.)
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="MEMBER_ID")
private Long id;
private String name;
private String street;
private String zipcode;
private String city;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
member에 그냥
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
하나 추가했다.
mappedBy = "member" 해서,
저 Order 엔티티의 member를 참조한다는 뜻이다.
이건 읽기전용이고, 주인이 아니기에 이 Member에서 order값을 바꿔봤자 DB에 반영되지 않는다.
그 다음 Order
@Entity
@Table(name="ORDERS")
public class Order {
@Id
@GeneratedValue
@Column(name="ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
}
여기도 마찬가지로,
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
이거 하나 추가했다.
마찬가지로 OrderItem에 있는 order라고 이름지어진 변수를 참조하도록 했다.
리스트에 new ArrayList<>(); 해놓는 건 관례인데,
저렇게 해야 .add() 해도 null 에러가 안나니까.
이제 뭐 만든 걸 이용해서 주문을 한다고 치면 대충
Order order = new Order();
em.persist(order);
OrderItem orderItem = new OrderItem();
orderItem.setOrder(order);
em.persist(orderItem);
이런 식으로.
근데 객체지향적으로 양방향으로 짜고 싶다면,
저 orderItem의 setOrder 대신
orderItem.addOrder 만들어서 (아 근데 이게 객체지향적으로 orderItem에 order를 추가하는 게 좀 이상하긴 한데.. order에서 orderItem을 추가하는 게 더 추상적으로 맞는 듯.)
그럼 다시, Order에다 orderItem을 추가하는 방향으로,
public void addOrderItem(OrderItem orderItem){
orderItems.add(orderItem);
orderItem.setOrder(this);
}
이렇게 Order에 만들어서,
Order order = new Order();
em.persist(order);
OrderItem orderItem = new OrderItem();
em.persist(orderItem);
order.addOrderItem(orderItem);
대충 이런 식으로..
어차피 update 쿼리는 영속성 컨텍스트에서 변화를 감지해 쓰기지연 SQL 저장소에 넣어진 다음 보내질 테니.
사실 양방향 연관관계가 꼭 필요한 것이 아니다.
그냥 조회하면 될 일이다.
근데 이번에 Order와 OrderItem은 마치 짝꿍처럼 따라다니는 것 이다.
개발 상 순조롭게 하기 위해 이렇게 하는 것 이다.
단방향 설계를 잘 하는 게 중요하고,
양방향 연관관계는 필요하다고 느껴지면 그 때 하는 것이 좋다.
'JPA > JPA 기본' 카테고리의 다른 글
20. 1:N 일대다 (0) | 2023.10.24 |
---|---|
19. N : 1 다대일, 다양한 연관관계 (0) | 2023.10.24 |
17. 양방향 연관관계 주의점 (0) | 2023.10.23 |
16. 양방향 연관관계와 연관관계의 주인 1 (0) | 2023.10.22 |
15. 연관관계 매핑 (0) | 2023.10.22 |