inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

주문 서비스 개발

양방향 @OneToOne 조회에 대해 질문 있습니다.

해결된 질문

143

감바스

작성한 질문수 92

0

@Entity
public class Delivery {

    @Id
    @Column(name = "delivery_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "delivery")
    private Order order;

    private Address address;

    @Enumerated(EnumType.STRING)
    private DeliveryStatus status;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public DeliveryStatus getStatus() {
        return status;
    }

    public void setStatus(DeliveryStatus status) {
        this.status = status;
    }
}
@Entity
@Table(name = "orders")
public class Order {

    @Id
    @Column(name = "order_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Delivery getDelivery() {
        return delivery;
    }

    public void setDelivery(Delivery delivery) {
        this.delivery = delivery;
    }

    public LocalDateTime getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(LocalDateTime orderDate) {
        this.orderDate = orderDate;
    }

    public OrderStatus getStatus() {
        return status;
    }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }
}
public class Test2 {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-pu");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        try {
            tx.begin();

            Delivery delivery = new Delivery();
            delivery.setStatus(DeliveryStatus.READY);
            delivery.setAddress(new Address("city", "street", "zipcode"));
            em.persist(delivery);
            Order order = new Order();
            order.setOrderDate(LocalDateTime.now());
            order.setStatus(OrderStatus.ORDER);
            order.setDelivery(delivery);
            em.persist(order);

            // Order 에 fetch = FetchType.LAZY 설정 , delivery 실제 값 사용
            {
                em.flush();
                em.clear();
                Order findOrder = em.find(Order.class, order.getId());
                Delivery findDelivery = findOrder.getDelivery();
                System.out.println("findDelivery : " + findDelivery.getStatus());
            }

            tx.commit();
        }finally {
            em.close();
        }
    }

}

실행결과

Hibernate: 
    /* insert for
        com.mycom.myapp.ex.Delivery */insert 
    into
        Delivery (city, street, zipcode, status) 
    values
        (?, ?, ?, ?)
Hibernate: 
    /* insert for
        com.mycom.myapp.ex.Order */insert 
    into
        orders (delivery_id, orderDate, status) 
    values
        (?, ?, ?)
Hibernate: 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.orderDate,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.order_id=?
Hibernate: 
    select
        d1_0.delivery_id,
        d1_0.city,
        d1_0.street,
        d1_0.zipcode,
        d1_0.status 
    from
        Delivery d1_0 
    where
        d1_0.delivery_id=?
Hibernate: 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.orderDate,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?
findDelivery : READY

강의에서 진행한 Order와 Delivery를 가지고 조회 테스트를 해봤습니다. 우선 Order와 Delivery를 양방향으로 OneToOne 관계를 설정했습니다. 그리고 둘다 각각 지연로딩으로 설정했습니다.

em.flush();
em.clear();
Order findOrder = em.find(Order.class, order.getId());
Delivery findDelivery = findOrder.getDelivery();
System.out.println("findDelivery : " + findDelivery.getStatus());

그리고 이 부분에 대해 아래와 같이 이해를 했습니다.

맨처음 em.find()를 해서 Order에 대해 DB에 select문을 보냅니다. 이때 delivery와는 지연로딩이므로 추가 select가 발생하지 않습니다.

그리고 findDelivery.getStatus()); 에서 delivery의 실제 값을 사용하므로 이때 delviery에 대한 select문이 발생합니다. 정리하면 처음에는 order에 대한 select문 그리고 실제 delevery 값을 사용할때 delivery에 대한 select문 해서 총 두번의 select문이 발생할꺼라고 예상을 했습니다.

근데 실제 실행결과를 보니 총 세번의 select문이 발생했습니다. 실행결과에서 첫번째 select문과 두번째 select문이 출력된거는 이해가 되는데 마지막 select문은 왜 발생했는지 모르겠습니다.

java spring 웹앱 spring-boot jpa

답변 1

0

y2gcoder

안녕하세요. 감바스님, 공식 서포터즈 y2gcoder입니다.

마지막은 findDelivery 에서 order를 로딩하기 때문에 발생하는 것으로 보입니다.

@OneToOne 양방향 관계에서는 지연 로딩이 먹지 않는 경우가 발생합니다 🙂

다음 링크(클릭)을 참고해주십쇼!

 

감사합니다.

1

감바스

감사합니다!

OrderServiceTest 상문주문 테스트 시 update 쿼리 문의

0

27

1

sdk 설정 오류

0

68

2

오탈자 - @Transactional

0

62

1

src/test/resources 테스트 경로 문제

0

56

1

상품 등록후 H2 db 출력 순서 바꿀 수 있나요?

0

70

1

MemberRepositoryTest 실행오류

0

90

1

boot 4.x >>> trasasction rolled back log & p6spy(영한님, 수업 자료 업데이트 해주시면 감사하겠습니다!!)

1

195

2

강의 마지막 QueryDSL 사용 부분 질문있습니다

1

153

2

클라이언트에서 isbn과 author 수정 요청을 한 경우에 대해 질문드립니다.

0

56

1

도메인 모델 패턴 vs 트랜잭션 스크립트 패턴

0

80

1

기본 생성자

0

67

1

h2 DB 연결시 jdbc url 변경 이유가 궁금합니다.

0

107

1

멤버서비스테스트 부분에서 막힙니다.

0

174

4

실무에서도 EntityManager를 이용해서 많이 작업하는 편일까요?

0

124

1

초반에 h2 다운로드 과정 꼭 필요한가요?

0

129

2

자신 필드에도 get으로 접근하는 이유가 있을까요?

0

121

1

24분 27초 연관관계 편의 메서드 위치

0

118

1

단건 주문만 가능하게 한건 의도한 부분이신가요?

0

114

2

빌드 툴, Gradle

0

63

1

h2연결은 된 것 같은데 엔티티 테이블까지 작성 후 확인해보아도 테이블이 안보입니다

0

81

2

Repository에서 EntityManager 주입 방식 차이

0

97

1

롬복과 사용자 정의 setter 메서드

0

77

1

주문 목록 조회 fetch join 질문드립니다

0

91

1

dirty checking 질문드립니다.

0

86

1