일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- insertion sort
- 윤성우의 열혈 자료구조
- Algorithm
- stream
- 이것이 자바다
- 혼자 공부하는 C언어
- 윤성우 열혈자료구조
- 메모리구조
- Graph
- Selection Sorting
- Stack
- 알기쉬운 알고리즘
- datastructure
- C 언어 코딩 도장
- 이스케이프 문자
- JSON
- C programming
- buffer
- list 컬렉션
- coding test
- R
- Serialization
- s
- Today
- Total
Engineering Note
[JPA] JPA save 쿼리메소드 실행시 내부 동작 흐름 정리 본문
내부 동작 흐름 정리 상황 설명
Order 엔티티가 있고, Order와 일대다 관계를 맺는 orderItem 엔티티를 cascde.all로 설정 해두었다. 이 상태에서 orderRepository.save(order)메서드를 정리하려고 한다.
package com.shop.entity;
import com.shop.contant.OrderStatus;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "orders")
@Getter
@Setter
public class Order extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "order_id")
private Long id;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
private LocalDateTime orderDate; //주문일
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus; //주문상태
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
}
1. orderRepository.save(order) 호출 시
1-1 Order 객체가 영속화
- Order 객체가 영속화 된다. 영속화의 의미는 JPA가 관리하는 메모리상의 객체를 관리하는 공간인 영속성 컨텍스트에 저장한다는 의미이다.
- 아직 DB에는 반영되지 않은 상태다.
1-2 Cascade 처리
- CascadeType.All 때문에, order.getOrderItems().add(orderItem)을 호출 했다면, order.getOrderItem() 안의 모든 OrderItem 객체도 모두 영속성 컨텍스트에 등록된다.
- 즉 부모 엔티티에 대한 상태 변화가 자식 엔티티에도 전파된다.
1-3 SQL 생성준비
- JPA는 SQL을 SQL 쓰기 지연 저장소에 저장한다.
- 아직 DB에는 save() 메서드에 해당하는 insert 쿼리문을 전송하지 않은 상태다.
2. 트랜잭션 종료시(@Transaction이 끝나거나 or flush() 호출시)
2-1 영속성 컨텍스트 객체를 DB에 반영
- 영속성 컨텍스트에 등록된 Order와 OrderItem 엔티티를 순서대로 DB에 insert 한다.
정리
DB 반영 시점은 flush/커밋 시점이고, save() 쿼리메서드 만으로는 지연 SQL 저장소에 쿼리가 쌓이는 구조이고, DB에 즉시 반영되지는 않는다.
DB에 바로 반영하고 싶다면 saveAndFlush() 쿼리메서드를 사용하면 된다.
실습 코드
package com.shop.entity;
import com.shop.contant.ItemSellStatus;
import com.shop.repository.ItemRepository;
import com.shop.repository.OrderRepository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@ActiveProfiles("test")
@Transactional
class OrderTest {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ItemRepository itemRepository;
@PersistenceContext
private EntityManager em;
public Item createItem() {
Item item = new Item();
item.setItemNm("테스트 상품");
item.setPrice(10000);
item.setItemDetail("상세설명");
item.setItemSellStatus(ItemSellStatus.SELL);
item.setStockNumber(100);
return item;
}
@Test
@DisplayName("영속성 전이 테스트")
public void cascadeTest() {
Order order = new Order();
for(int i = 0; i < 3; i++) {
Item item = this.createItem();
itemRepository.save(item);
OrderItem orderItem = new OrderItem();
orderItem.setItem(item);
orderItem.setCount(10);
orderItem.setOrderPrice(item.getPrice());
orderItem.setOrder(order);
order.getOrderItems().add(orderItem);
}
System.out.println("save order");
orderRepository.saveAndFlush(order); //저장하면서 em.flush 호출, 영속성 컨텍스트 객체를 DB indert문 전송, save만 하면 영속성 컨텍스트에만 저장 트랜잭션 끝날 때 flush 호출
System.out.println("save order flush 완료");
System.out.println("영속성 컨텍스트 클리어");
em.clear();
Order savedOrder = orderRepository.findById(order.getId()).orElseThrow(EntityNotFoundException::new);
assertEquals(3, savedOrder.getOrderItems().size());
}
}
saveAndFlush() 호출시 출력된 쿼리문
orders와 oder_item에 insert 쿼리가 전송된다. 중간에 테스트를 위해 영속석 컨텍스트 초기화를 해두었는데(em.clear()) 그래서 Order 객체 조회시 select 쿼리가 실행된다.
'Server > JPA ORM' 카테고리의 다른 글
[JPA] 영속성 컨텍스트 생명주기와 @Transacional의 동작 원리: 영속성 컨텍스트 유지 (0) | 2025.10.05 |
---|---|
[JPA] 영속성 전이와 고아객체 제거 (0) | 2025.09.14 |
[JPA] @Enumerated 어노테이션 (0) | 2025.09.14 |
[JPA] JPA 동작 방식 (0) | 2025.09.08 |
[JPA] 지연로딩(Lazy Loading)으로 인한 N+1 문제 (0) | 2025.08.22 |