Polymor!

[Spring] JPA 쿼리 분석 (1) 연관관계 정의 본문

Web

[Spring] JPA 쿼리 분석 (1) 연관관계 정의

Megan Kim 2021. 3. 11. 12:08

1 : N (일대다) 연관 관계를 갖는 Cart와 CartItem을 상상하자. 

 

1개의 Cart는 N개의 CartItem을 가질 수 있다. 양방향 연관관계 매핑을 아래와 같이 한다. 

CascadeType.ALL은 영속성을 전이하는 것이다. Cart의 영속성이 연관관계를 갖는 CartItem list Entities에 전이되는 것 뿐이다.그러나 Cart가 CartItem의 변경감지를 대신해주진 않음 절대로.

 

// Cart Entity 

@OneToMany(fetch = FetchType.LAZY,mappedBy="cart",cascade = CascadeType.ALL, orphanRemoval = true)    // 02-15 Megan
    private List<CartItem> cartItems;
// CartItem Entity

@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "cart_id")

 

 

* Cart가 가지고 있는 연관 엔티티 CartItem 들 중 하나의 quantity 값을 수정한다고 가정하자. 

 

 

1. Cart 영속성 : 없음 -> CartItem 영속성 : 없음

( @Service logic에는 @transactional 없고, getCartItems()는 cart 엔티티 내부 메서드이다. != repo)

 public void UpdateItemQuantity(long cartid,Integer quantity) {

        
         Cart cart = this.findById(cartid);

         cart.getCartItems().get(0).UpdateQuantity(quantity);
        
        

    }

 

결과: Select 2회 (FetchType.Lazy로 설정했기때문에 getCartItems() 호출 시에 두번째 쿼리가 날라간다.)

Hibernate: select cart0_.cart_id as cart_id1_1_0_, cart0_.account_id as account20_1_0_, cart0_.address as address2_1_0_, cart0_.city as city3_1_0_, cart0_.content as content4_1_0_, cart0_.country as country5_1_0_, cart0_.created_at as created_6_1_0_, cart0_.grand_total as grand_to7_1_0_, cart0_.item_discount as item_dis8_1_0_, cart0_.item_price_total as item_pri9_1_0_, cart0_.province as provinc10_1_0_, cart0_.road_address as road_ad11_1_0_, cart0_.session_id as session12_1_0_, cart0_.shipping as shippin13_1_0_, cart0_.status as status14_1_0_, cart0_.tax as tax15_1_0_, cart0_.token as token16_1_0_, cart0_.updated_at as updated17_1_0_, cart0_.user_discount as user_di18_1_0_, cart0_.zip_code as zip_cod19_1_0_ from shop.cart cart0_ where cart0_.cart_id=?


Hibernate: select cartitems0_.cart_id as cart_id10_2_0_, cartitems0_.cart_item_id as cart_ite1_2_0_, cartitems0_.cart_item_id as cart_ite1_2_1_, cartitems0_.active as active2_2_1_, cartitems0_.cart_id as cart_id10_2_1_, cartitems0_.content as content3_2_1_, cartitems0_.created_at as created_4_2_1_, cartitems0_.discount_price as discount5_2_1_, cartitems0_.price as price6_2_1_, cartitems0_.product_id as product11_2_1_, cartitems0_.quantity as quantity7_2_1_, cartitems0_.sku as sku8_2_1_, cartitems0_.updated_at as updated_9_2_1_ from shop.cart_item cartitems0_ where cartitems0_.cart_id=?

 

 

 

 

2. Cart 영속성 : 저장 -> CartItem 영속성 : 저장 

 public void UpdateItemQuantity(long cartid,Integer quantity) {

        
         Cart cart = this.findById(cartid);

         cart.getCartItems().get(0).UpdateQuantity(quantity);
        
        
         save(cart);
    }

 

결과 : Select 2회 + update 1회 (Cart는 변경감지 없으므로 CartItem만 update 쿼리날림)

Hibernate: select cart0_.cart_id as cart_id1_1_0_, cart0_.account_id as account20_1_0_, cart0_.address as address2_1_0_, cart0_.city as city3_1_0_, cart0_.content as content4_1_0_, cart0_.country as country5_1_0_, cart0_.created_at as created_6_1_0_, cart0_.grand_total as grand_to7_1_0_, cart0_.item_discount as item_dis8_1_0_, cart0_.item_price_total as item_pri9_1_0_, cart0_.province as provinc10_1_0_, cart0_.road_address as road_ad11_1_0_, cart0_.session_id as session12_1_0_, cart0_.shipping as shippin13_1_0_, cart0_.status as status14_1_0_, cart0_.tax as tax15_1_0_, cart0_.token as token16_1_0_, cart0_.updated_at as updated17_1_0_, cart0_.user_discount as user_di18_1_0_, cart0_.zip_code as zip_cod19_1_0_ from shop.cart cart0_ where cart0_.cart_id=?
Hibernate: select cartitems0_.cart_id as cart_id10_2_0_, cartitems0_.cart_item_id as cart_ite1_2_0_, cartitems0_.cart_item_id as cart_ite1_2_1_, cartitems0_.active as active2_2_1_, cartitems0_.cart_id as cart_id10_2_1_, cartitems0_.content as content3_2_1_, cartitems0_.created_at as created_4_2_1_, cartitems0_.discount_price as discount5_2_1_, cartitems0_.price as price6_2_1_, cartitems0_.product_id as product11_2_1_, cartitems0_.quantity as quantity7_2_1_, cartitems0_.sku as sku8_2_1_, cartitems0_.updated_at as updated_9_2_1_ from shop.cart_item cartitems0_ where cartitems0_.cart_id=?
2021-03-11 11:42:33.445  INFO 1088 --- [  restartedMain] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: findOrderIdUsingGET_1
Hibernate: update shop.cart_item set active=?, cart_id=?, content=?, created_at=?, discount_price=?, price=?, product_id=?, quantity=?, sku=?, updated_at=? where cart_item_id=?

 

 

 

3. Cart 영속성 : 변경감지로 인한 저장 -> CartItem 영속성 : 저장 

@transactional 
public void UpdateItemQuantity(long cartid,Integer quantity) {

        
         Cart cart = this.findById(cartid);

         cart.getCartItems().get(0).UpdateQuantity(quantity);
        
        
         cart.updateItem(1000,10,10);
         
    }

결과 : Select 2회 + update 2회 

Hibernate: select cart0_.cart_id as cart_id1_1_0_, cart0_.account_id as account20_1_0_, cart0_.address as address2_1_0_, cart0_.city as city3_1_0_, cart0_.content as content4_1_0_, cart0_.country as country5_1_0_, cart0_.created_at as created_6_1_0_, cart0_.grand_total as grand_to7_1_0_, cart0_.item_discount as item_dis8_1_0_, cart0_.item_price_total as item_pri9_1_0_, cart0_.province as provinc10_1_0_, cart0_.road_address as road_ad11_1_0_, cart0_.session_id as session12_1_0_, cart0_.shipping as shippin13_1_0_, cart0_.status as status14_1_0_, cart0_.tax as tax15_1_0_, cart0_.token as token16_1_0_, cart0_.updated_at as updated17_1_0_, cart0_.user_discount as user_di18_1_0_, cart0_.zip_code as zip_cod19_1_0_ from shop.cart cart0_ where cart0_.cart_id=?
Hibernate: select cartitems0_.cart_id as cart_id10_2_0_, cartitems0_.cart_item_id as cart_ite1_2_0_, cartitems0_.cart_item_id as cart_ite1_2_1_, cartitems0_.active as active2_2_1_, cartitems0_.cart_id as cart_id10_2_1_, cartitems0_.content as content3_2_1_, cartitems0_.created_at as created_4_2_1_, cartitems0_.discount_price as discount5_2_1_, cartitems0_.price as price6_2_1_, cartitems0_.product_id as product11_2_1_, cartitems0_.quantity as quantity7_2_1_, cartitems0_.sku as sku8_2_1_, cartitems0_.updated_at as updated_9_2_1_ from shop.cart_item cartitems0_ where cartitems0_.cart_id=?
2021-03-11 11:42:33.445  INFO 1088 --- [  restartedMain] .d.s.w.r.o.CachingOperationNameGenerator : Generating unique operation named: findOrderIdUsingGET_1
Hibernate: update shop.cart set account_id=?, address=?, city=?, content=?, country=?, created_at=?, grand_total=?, item_discount=?, item_price_total=?, province=?, road_address=?, session_id=?, shipping=?, status=?, tax=?, token=?, updated_at=?, user_discount=?, zip_code=? where cart_id=?
Hibernate: update shop.cart_item set active=?, cart_id=?, content=?, created_at=?, discount_price=?, price=?, product_id=?, quantity=?, sku=?, updated_at=? where cart_item_id=?

 

 

 

 

(참고) FetchType.Lazy vs FetchType.Eager 

# fetchType.LAZY - cartItem 정보 없음

Hibernate: select cart0_.cart_id as cart_id1_1_0_, cart0_.account_id as account20_1_0_, cart0_.address as address2_1_0_, cart0_.city as city3_1_0_, cart0_.content as content4_1_0_, cart0_.country as country5_1_0_, cart0_.created_at as created_6_1_0_, cart0_.grand_total as grand_to7_1_0_, cart0_.item_discount as item_dis8_1_0_, cart0_.item_price_total as item_pri9_1_0_, cart0_.province as provinc10_1_0_, cart0_.road_address as road_ad11_1_0_, cart0_.session_id as session12_1_0_, cart0_.shipping as shippin13_1_0_, cart0_.status as status14_1_0_, cart0_.tax as tax15_1_0_, cart0_.token as token16_1_0_, cart0_.updated_at as updated17_1_0_, cart0_.user_discount as user_di18_1_0_, cart0_.zip_code as zip_cod19_1_0_ 
           from shop.cart cart0_ 
           where cart0_.cart_id=?



#fetchType.EAGER - join 해서 다 가져옴

Hibernate: select cart0_.cart_id as cart_id1_1_0_, cart0_.account_id as account20_1_0_, cart0_.address as address2_1_0_, cart0_.city as city3_1_0_, cart0_.content as content4_1_0_, cart0_.country as country5_1_0_, cart0_.created_at as created_6_1_0_, cart0_.grand_total as grand_to7_1_0_, cart0_.item_discount as item_dis8_1_0_, cart0_.item_price_total as item_pri9_1_0_, cart0_.province as provinc10_1_0_, cart0_.road_address as road_ad11_1_0_, cart0_.session_id as session12_1_0_, cart0_.shipping as shippin13_1_0_, cart0_.status as status14_1_0_, cart0_.tax as tax15_1_0_, cart0_.token as token16_1_0_, cart0_.updated_at as updated17_1_0_, cart0_.user_discount as user_di18_1_0_, cart0_.zip_code as zip_cod19_1_0_, cartitems1_.cart_id as cart_id10_2_1_, cartitems1_.cart_item_id as cart_ite1_2_1_, cartitems1_.cart_item_id as cart_ite1_2_2_, cartitems1_.active as active2_2_2_, cartitems1_.cart_id as cart_id10_2_2_, cartitems1_.content as content3_2_2_, cartitems1_.created_at as created_4_2_2_, cartitems1_.discount_price as discount5_2_2_, cartitems1_.price as price6_2_2_, cartitems1_.product_id as product11_2_2_, cartitems1_.quantity as quantity7_2_2_, cartitems1_.sku as sku8_2_2_, cartitems1_.updated_at as updated_9_2_2_ 
           from shop.cart cart0_ 
           left outer join shop.cart_item cartitems1_ on cart0_.cart_id=cartitems1_.cart_id 
           where cart0_.cart_id=?

 

Comments