| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 혼자 공부하는 C언어
- 윤성우 열혈자료구조
- 알기쉬운 알고리즘
- coding test
- ㅅ
- 이스케이프 문자
- insertion sort
- s
- Graph
- Algorithm
- Selection Sorting
- 메모리구조
- Stack
- 윤성우의 열혈 자료구조
- Serialization
- JSON
- datastructure
- C programming
- buffer
- R
- list 컬렉션
- 이것이 자바다
- C 언어 코딩 도장
- stream
- Today
- Total
Engineering Note
[JPA] 영속성 전이 옵션과 연관관계 편의 메서드가 필요한 이유, 고아객체 설정 본문
[JPA] 영속성 전이 옵션과 연관관계 편의 메서드가 필요한 이유, 고아객체 설정
Software Engineer Kim 2026. 1. 10. 21:22
영속성 전이 옵션과 연관관계 편의 메서드가 필요한 이유
cascade = CascadeType.ALL
cacade 영속성 전이 옵션은 부모의 영속상태의 생명주기를 자식과 함께 하겠다는 설정이다.
JPA를 사용하면 연관관계 관리를 편리하기 위해 연관관계 편의 메서드라고 불리는 메서드를 만들어서 사용한다.
아래 메서드는 연관관계를 편리하게 하기 위한 메서드이다. '연관관계 편의 메서드'라고 특별한 이름이 붙었지만, Java입장에서는 필드를 세팅해주는 메서드다. 하지만 JPA는 Java의 객체 세계와 DB의 관계형 세계를 함께 다루어야 하기 때문에 Java의 철학과는 조금은 다른 형태로 존재하는 메서드라 처음에는 낯설 수 있다.
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
이커머스 환경에서 Order엔티티와 OrderItem엔티티가 있다. OrderItem 엔티티는 Order가 없이는 존재할 수 없는 엔티티다. DB관점에서 OrderItem은 Order의 기본키를 참조하는 외래키를 갖는다.
비즈니스 로직에서 주문이 생성되어서 Order Entity가 생성되고 저장해야 하는 상황에서 OrderItem도 따로 저장하지 않고 한 번에 관리하기 위해 연관관계 메서드가 필요하다.
주문 생성 정적 팩토리 메서드
public static Order createOrder(Member member, List<OrderItem> orderItemList) {
Order order = new Order();
//연관관계 세팅
order.setMember(member);
for(OrderItem orderItem : orderItemList) {
order.addOrderItem(orderItem);
}
order.setOrderStatus(OrderStatus.ORDER);
order.setOrderDate(LocalDateTime.now());
return order;
}
주문 서비스 로직
public Long order(OrderDto orderDto, String email) {
Item item = itemRepository.findByIdForUpdate(orderDto.getItemId()).orElseThrow(EntityNotFoundException::new);
Member member = memberRepository.findByEmail(email);
List<OrderItem> orderItemList = new ArrayList<>();
OrderItem orderItem = OrderItem.createOrderItem(item, orderDto.getQuantity());
orderItemList.add(orderItem);
Order order = Order.createOrder(member, orderItemList);
log.info("========주문 정보 저장=========");
orderRepository.save(order);
log.info("========주문 정보 저장 완료=========");
return order.getId();
}
주문 서비스 로직을 보면 OrderItem은 저장하는 코드가 없다. 오직 주문을 저장하는 ' orderRepository.save(order);' 코드만 있다.
========주문 정보 저장=========
2026-01-10T21:12:01.257+09:00 DEBUG 82173 --- [shop] [ main] org.hibernate.SQL :
insert
into
orders
(created_by, member_id, modified_by, order_date, order_status, reg_time, order_id)
values
(?, ?, ?, ?, ?, ?, default)
insert
into
order_item
(created_by, item_id, modified_by, order_id, order_price, quantity, reg_time, order_item_id)
values
(?, ?, ?, ?, ?, ?, ?, default)
========주문 정보 저장 완료=========
코드를 실행시켜 보면 order를 저장하는 SQL과 order_item을 저장하는 SQL이 실행되었다. 이러한 일이 가능한 이유는 '영속성 전이 설정'때문이다. 그리고 영속성 전이 설정이 정상 동작하도록 하기위해 orderRepository(order);를 수행하기 전에 연관관계 편의 메서드를 통해 orderItem을 세팅해주었기 때문이다.
그런데 여기서 주의할 점은 JPA에서 외래키는 부모가 아니라 자식 엔티티가 관리하기 때문에 부모에 있는 List<OrderItem> orderItems만 세팅해준다고 외래키가 세팅되지는 않는다. 위에 addOrderItem(OrderItem orderItem) 메서드 내부에서 두 줄의 코드가 있는 이유다. 첫 줄에 orderItems.add(orderItem);은 Order엔티티의 'orderItems' 필드를 채우기 위한 코드고, 두 번째 줄의 orderItems.setOrder(this);가 외래키를 세팅해주기 위한 코드다. 다시 한 번 강조하지만 JPA는 연관관계주인인 자식 엔티티가 외래키를 관리하기 때문이다.
그런데 외래키를 관리한다고 두 번째 줄만 작성하는 것도 오류를 발생시킬 수 있다. Java 객체로 생성된 Order entity의 orderItems이 세팅되지 않으면 맥락적으로 문제가 있기 때문이다. JPA는 트랜잭션 안에서 성능을 위해 Entity를 1차캐시에 저장하고 활용하는데 Order가 다시 조회되어 orderItems를 조회한다면, 외래키만 생각한 코드는 오류를 발생시킨다.
'Server > JPA ORM' 카테고리의 다른 글
| [JPA] N+1문제가 발생하는 예(주문내역 조회) (1) | 2026.01.23 |
|---|---|
| [JPA] JPA에서 연관관계가 맺어진 객체를 비교(eq)하는 것은, 실제 DB에서는 그 객체의 'ID(PK) 값'을 비교하는 것과 완전히 동일하다. (0) | 2026.01.14 |
| [JPA] JPA 활용 주의점과 사용팁 (0) | 2026.01.06 |
| [JPA] 컬렉션 Fetch Join 페이지네이션 문제와 해결책 (0) | 2025.12.29 |
| [JPA] Repository로 동시성 테스트하면 안 되는 이유 (0) | 2025.12.24 |