스프링데이터 + JPA/API 개발

6. 지연로딩과 조회성능 최적화

sdafdq 2023. 11. 13. 11:38

주문(Order) + 배송정보(Delivery) + 회원(Member) 조회하는 API를 만들거임.

점차적으로 성능을 향상시킬거임.

 

xToOne은 기본이 즉시로딩이라, 명시적으로 LAZY로딩으로 해 줘야 함.

 

 

일단은, 이런 연관관계 무시하고,

@GetMapping("/api/v1/simple-orders")
public List<Order> ordersV1(){
    List<Order> all = orderRepository.findAllString(new OrderSearch());
    return all;
}

 

이렇게 하면 무한루프에 빠짐.

왜냐하면,

@Entity
@Table(name = "orders")
@Getter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
public class Order {
    @Id @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

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

    private LocalDateTime orderDate;


    @Enumerated(EnumType.STRING)
    private OrderStatus status;
}

order 엔티티인데 양방향 연관관계라 order가 member 조회해오고 member안에 있는 order들 조회해오고 또 그 order안에 있는 member조회해오고 또 그 member안에있는 order들 조회해오고..

 

양방향은 이렇게 끝이 안남. 거울끼리 서로 마주보게 하는 그런 느낌임.

 

이럴 경우 우선 해결법은,

Order에서 양방향 걸려있는 애들,

@JsonIgnore
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
@JsonIgnore
private Order order;
@OneToOne(mappedBy = "delivery", fetch = FetchType.LAZY)
@JsonIgnore
private Order order;


걔네들 다 찾아가서 @JsonIgnore 해서 Json 거부 해준다.

그러면 거부 했으니, 얘네껀 안 읽고 Order것만 읽겠지..?

즉, 우리가 Order를 조회해 오는거니 얘네들은 Order를 조회해 오면 안된다. 그러면 무한루프에 빠지니까.

그러니까 어떤 양방향 연관관계에 있는 애들은 싹다 @JsonIgnore 해 줘서 api, 즉 json으로 가져오는 것을 거부해준다.

이미 order는 있다.

 

근데 이것도 문제가 있다.

LAZY는 프록시로 씌워서 가져온다.

객체를 json으로 변환해주는 jackson 라이브러리는 jpa꺼가 아니라서 저 씌워주는 프록시에 대한 정체를 모른다.

얘는 그냥 Order라는 것을 json으로 변환하려고 했는데, 무슨 이상한 프록시 객체인 것이다.

그래서,

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0]->jpabook.jpashop.domain.Order["member"]->jpabook.jpashop.domain.Member$HibernateProxy$46Sq1l6W["hibernateLazyInitializer"])
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1308) ~[jackson-databind-2.15.3.jar:2.15.3]
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:414) ~[jackson-databind-2.15.3.jar:2.15.3]

대충 이런 식으로 no serializer 직렬화, 직렬적으로 데이터를 바꿔주는 그런 것을 찾을 수 없다는 것이다. 어댑터 패턴인가 보다. 

 

여튼, 또 이거의 해결 방법은

그냥 하이버네이트보고 지연로딩의 경우 호출해서 정상적으로 로딩한 것들 말고는 그냥 json으로 뿌리지 말라고 할 수 있다.(프록시인 애들은 먼저 뿌리지 않았다가, 만져서 로딩하면 그 로딩한 것들만 뿌린다.)

 

그럴려면 우선 잭슨의 하이버네이트와 관련된 모듈을 가져와야 한다.

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5-jakarta'

 

그 다음 그냥 아무데나 빈으로 등록시켜준다.

 

@SpringBootApplication
public class JpashopApplication {
	public static void main(String[] args) {
		SpringApplication.run(JpashopApplication.class, args);
	}

	@Bean
	Hibernate5JakartaModule hibernate5Module(){
		return new Hibernate5JakartaModule();
	}
}

걍 메인에다 빈으로 했음

 

그러면 이제, 조회 해보면 뭐 @JsonIgnore이런 것도 이제 안해줘도 되고 (그래도 @JsonIgnore는 무조건 명시해 줘야 함),

[
    {
        "id": 1,
        "member": null,
        "orderItems": null,
        "delivery": null,
        "orderDate": "2023-11-13T12:08:24.019551",
        "status": "ORDER",
        "totalPrice": 50000
    },
    {
        "id": 2,
        "member": null,
        "orderItems": null,
        "delivery": null,
        "orderDate": "2023-11-13T12:08:24.099505",
        "status": "ORDER",
        "totalPrice": 220000
    }
]

이렇게 지연로딩인 건 null로 가져옴.

 

 

근데, 우리는 이것도 안쓸거임.

애초에 api를 클라이언트로부터 엔티티로 받거나 주지를 않을거임.

 

저게 하이버네이트 모듈 기본 설정이 LAZY는 null로 가져오는 거라서 null로 가져오는 거고, FORCE_LAZY_LODING 또 이렇게 설정하게끔 할 수 있는데 그러면 그 때는 잘 가져옴.

[
    {
        "id": 1,
        "member": {
            "id": 1,
            "name": "userA",
            "address": {
                "city": "서울",
                "street": "1",
                "zipcode": "1111"
            }
        },
        "orderItems": [
            {
                "id": 1,
                "item": {
                    "id": 1,
                    "name": "JPA1 BOOK",
                    "price": 10000,
                    "stockQuantity": 99,
                    "categories": [],
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 10000,
                "count": 1,
                "totalPrice": 10000
            },
            {
                "id": 2,
                "item": {
                    "id": 2,
                    "name": "JPA2 BOOK",
                    "price": 20000,
                    "stockQuantity": 98,
                    "categories": [],
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 20000,
                "count": 2,
                "totalPrice": 40000
            }
        ],
        "delivery": {
            "id": 1,
            "address": {
                "city": "서울",
                "street": "1",
                "zipcode": "1111"
            },
            "status": "READY"
        },
        "orderDate": "2023-11-13T12:18:34.543708",
        "status": "ORDER",
        "totalPrice": 50000
    },
    {
        "id": 2,
        "member": {
            "id": 2,
            "name": "userB",
            "address": {
                "city": "진주",
                "street": "2",
                "zipcode": "2222"
            }
        },
        "orderItems": [
            {
                "id": 3,
                "item": {
                    "id": 3,
                    "name": "SPRING1 BOOK",
                    "price": 20000,
                    "stockQuantity": 197,
                    "categories": [],
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 20000,
                "count": 3,
                "totalPrice": 60000
            },
            {
                "id": 4,
                "item": {
                    "id": 4,
                    "name": "SPRING2 BOOK",
                    "price": 40000,
                    "stockQuantity": 296,
                    "categories": [],
                    "author": null,
                    "isbn": null
                },
                "orderPrice": 40000,
                "count": 4,
                "totalPrice": 160000
            }
        ],
        "delivery": {
            "id": 2,
            "address": {
                "city": "진주",
                "street": "2",
                "zipcode": "2222"
            },
            "status": "READY"
        },
        "orderDate": "2023-11-13T12:18:34.623662",
        "status": "ORDER",
        "totalPrice": 220000
    }
]

 

물론 이거 @JsonIgnore 해 줘서 명시적으로 알려줘야 하긴 함.. 하이버네이트 모듈이 @JsonIgnore는 따로 읽는 모양인가 보네.

근데 이것도 하지 마셈.

나가는 쿼리 보면,

    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    join
        member m1_0 
            on m1_0.member_id=o1_0.member_id 
    fetch
        first ? rows only
2023-11-13T12:18:42.302+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [INTEGER] - [1000]
2023-11-13T12:18:42.303+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522303 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first 1000 rows only;
2023-11-13T12:18:42.381+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T12:18:42.382+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.382+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522382 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=1;
2023-11-13T12:18:42.394+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.order_item_id,
        o1_0.count,
        o1_0.item_id,
        o1_0.order_price 
    from
        order_item o1_0 
    where
        o1_0.order_id=?
2023-11-13T12:18:42.395+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.395+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522395 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=?
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=1;
2023-11-13T12:18:42.398+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        i1_0.item_id,
        i1_0.dtype,
        i1_0.name,
        i1_0.price,
        i1_0.stock_quantity,
        i1_0.artist,
        i1_0.etc,
        i1_0.author,
        i1_0.isbn,
        i1_0.actor,
        i1_0.director 
    from
        item i1_0 
    where
        i1_0.item_id=?
2023-11-13T12:18:42.399+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.399+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522399 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=?
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=1;
2023-11-13T12:18:42.403+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        c1_0.item_id,
        c1_1.category_id,
        c1_1.name,
        c1_1.parent_id 
    from
        category_item c1_0 
    join
        category c1_1 
            on c1_1.category_id=c1_0.category_id 
    where
        c1_0.item_id=?
2023-11-13T12:18:42.403+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.404+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522404 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=?
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=1;
2023-11-13T12:18:42.404+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        i1_0.item_id,
        i1_0.dtype,
        i1_0.name,
        i1_0.price,
        i1_0.stock_quantity,
        i1_0.artist,
        i1_0.etc,
        i1_0.author,
        i1_0.isbn,
        i1_0.actor,
        i1_0.director 
    from
        item i1_0 
    where
        i1_0.item_id=?
2023-11-13T12:18:42.405+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:18:42.405+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522405 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=?
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=2;
2023-11-13T12:18:42.406+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        c1_0.item_id,
        c1_1.category_id,
        c1_1.name,
        c1_1.parent_id 
    from
        category_item c1_0 
    join
        category c1_1 
            on c1_1.category_id=c1_0.category_id 
    where
        c1_0.item_id=?
2023-11-13T12:18:42.406+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:18:42.407+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522407 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=?
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=2;
2023-11-13T12:18:42.410+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    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=?
2023-11-13T12:18:42.410+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.411+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522411 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
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=?
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=1;
2023-11-13T12:18:42.414+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?
2023-11-13T12:18:42.414+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:18:42.415+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522415 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=?
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=1;
2023-11-13T12:18:42.417+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T12:18:42.417+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:18:42.417+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522417 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=2;
2023-11-13T12:18:42.418+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.order_item_id,
        o1_0.count,
        o1_0.item_id,
        o1_0.order_price 
    from
        order_item o1_0 
    where
        o1_0.order_id=?
2023-11-13T12:18:42.418+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:18:42.418+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522418 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=?
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=2;
2023-11-13T12:18:42.419+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        i1_0.item_id,
        i1_0.dtype,
        i1_0.name,
        i1_0.price,
        i1_0.stock_quantity,
        i1_0.artist,
        i1_0.etc,
        i1_0.author,
        i1_0.isbn,
        i1_0.actor,
        i1_0.director 
    from
        item i1_0 
    where
        i1_0.item_id=?
2023-11-13T12:18:42.420+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [3]
2023-11-13T12:18:42.420+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522420 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=?
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=3;
2023-11-13T12:18:42.421+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        c1_0.item_id,
        c1_1.category_id,
        c1_1.name,
        c1_1.parent_id 
    from
        category_item c1_0 
    join
        category c1_1 
            on c1_1.category_id=c1_0.category_id 
    where
        c1_0.item_id=?
2023-11-13T12:18:42.421+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [3]
2023-11-13T12:18:42.421+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522421 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=?
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=3;
2023-11-13T12:18:42.422+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        i1_0.item_id,
        i1_0.dtype,
        i1_0.name,
        i1_0.price,
        i1_0.stock_quantity,
        i1_0.artist,
        i1_0.etc,
        i1_0.author,
        i1_0.isbn,
        i1_0.actor,
        i1_0.director 
    from
        item i1_0 
    where
        i1_0.item_id=?
2023-11-13T12:18:42.422+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [4]
2023-11-13T12:18:42.422+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522422 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=?
select i1_0.item_id,i1_0.dtype,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.artist,i1_0.etc,i1_0.author,i1_0.isbn,i1_0.actor,i1_0.director from item i1_0 where i1_0.item_id=4;
2023-11-13T12:18:42.423+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        c1_0.item_id,
        c1_1.category_id,
        c1_1.name,
        c1_1.parent_id 
    from
        category_item c1_0 
    join
        category c1_1 
            on c1_1.category_id=c1_0.category_id 
    where
        c1_0.item_id=?
2023-11-13T12:18:42.423+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [4]
2023-11-13T12:18:42.423+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522423 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=?
select c1_0.item_id,c1_1.category_id,c1_1.name,c1_1.parent_id from category_item c1_0 join category c1_1 on c1_1.category_id=c1_0.category_id where c1_0.item_id=4;
2023-11-13T12:18:42.424+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    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=?
2023-11-13T12:18:42.424+09:00 TRACE 11000 --- [nio-8080-exec-2] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:18:42.424+09:00  INFO 11000 --- [nio-8080-exec-2] p6spy                                    : #1699845522424 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
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=?
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=2;
2023-11-13T12:18:42.425+09:00 DEBUG 11000 --- [nio-8080-exec-2] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?

어마어마하게 많이 나감.

 

 

하이버네이트 모듈 자체를 LAZY로딩 때문에 쓰는 게 애매하기도 하고, 클라이언트로부터 받아오는걸 엔티티 자체로 받아오는 것도 나쁨.

 

하이버네이트 모듈 자체는 뭐 상황에 따라 필요할 수도 있겠지만, 일단 엔티티 자체를 저렇게 받는 것은 나쁜거고 일단,

 

LAZY로딩 특성을 이용해서 원하는 것만 가져오는 방법이 있다.

@SpringBootApplication
public class JpashopApplication {
	public static void main(String[] args) {
		SpringApplication.run(JpashopApplication.class, args);
	}

	@Bean
	Hibernate5JakartaModule hibernate5Module(){
		return new Hibernate5JakartaModule();
	}
}

이렇게 아무것도 안한 모듈 기본 설정으로.

 

그냥 for문 하면서 조회 시켜버리면 된다.

그런데 그것도.. for문 돌며 접근할 때마다 select 문을 보내게 된다..

@GetMapping("/api/v1/simple-orders")
public List<Order> ordersV1(){
    List<Order> all = orderRepository.findAllString(new OrderSearch());
    for (Order order : all) {
        order.getMember().getName();
        order.getDelivery().getAddress();
    }
    return all;
}

 

    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    join
        member m1_0 
            on m1_0.member_id=o1_0.member_id 
    fetch
        first ? rows only
2023-11-13T12:52:45.948+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [INTEGER] - [1000]
2023-11-13T12:52:45.948+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565948 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first 1000 rows only;
2023-11-13T12:52:45.968+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T12:52:45.972+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:52:45.973+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565973 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=1;
2023-11-13T12:52:45.978+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    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=?
2023-11-13T12:52:45.978+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:52:45.979+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565979 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
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=?
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=1;
2023-11-13T12:52:45.982+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?
2023-11-13T12:52:45.982+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:52:45.983+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565983 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=?
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=1;
2023-11-13T12:52:45.984+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        m1_0.member_id,
        m1_0.city,
        m1_0.street,
        m1_0.zipcode,
        m1_0.name 
    from
        member m1_0 
    where
        m1_0.member_id=?
2023-11-13T12:52:45.984+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:52:45.984+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565984 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=?
select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=2;
2023-11-13T12:52:45.985+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    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=?
2023-11-13T12:52:45.985+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:52:45.985+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565985 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
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=?
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=2;
2023-11-13T12:52:45.986+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.delivery_id,
        o1_0.member_id,
        o1_0.order_date,
        o1_0.status 
    from
        orders o1_0 
    where
        o1_0.delivery_id=?
2023-11-13T12:52:45.986+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [2]
2023-11-13T12:52:45.987+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847565987 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=?
select o1_0.order_id,o1_0.delivery_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.delivery_id=2;
2023-11-13T12:52:46.054+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.order_item_id,
        o1_0.count,
        o1_0.item_id,
        o1_0.order_price 
    from
        order_item o1_0 
    where
        o1_0.order_id=?
2023-11-13T12:52:46.055+09:00 TRACE 12948 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind              : binding parameter [1] as [BIGINT] - [1]
2023-11-13T12:52:46.056+09:00  INFO 12948 --- [nio-8080-exec-1] p6spy                                    : #1699847566056 | took 0ms | statement | connection 7| url jdbc:h2:tcp://localhost/./jpashop
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=?
select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where o1_0.order_id=1;
2023-11-13T12:52:46.059+09:00 DEBUG 12948 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        o1_0.order_id,
        o1_0.order_item_id,
        o1_0.count,
        o1_0.item_id,
        o1_0.order_price 
    from
        order_item o1_0 
    where
        o1_0.order_id=?

 

 

 

엔티티 클라이언트에게 직접 받거나 주지 말고, Dto로 받거나 준다.
지연로딩만 사용해라. XToOne은 즉시 로딩이 기본이다. 

연관관계 애노테이션에서 명시를 해 줘야 한다.

https://qwefdg3.tistory.com/755

 

성능 최적화가 필요한 경우 fetch join 사용

 

'스프링데이터 + JPA > API 개발' 카테고리의 다른 글

8. fetch join 최적화  (0) 2023.11.13
7. 엔티티를 Dto로  (0) 2023.11.13
5. 조회용 샘플 데이터 입력  (0) 2023.11.12
4. API 성능 최적화  (0) 2023.11.12
3. 회원 조회 API  (0) 2023.11.12