jpa n+1

greenTeaยท2023๋…„ 4์›” 11์ผ
0

๐Ÿคjpa์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ๋•Œ fetch type์„ Lazy๋กœ ์„ค์ •ํ•˜์˜€๋‹ค๋ฉด n+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Order

@Entity
public class Order {

    @Id
    private Long id;
    
    @OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
    private List<OrderItem> orderItems;
  
}

OrderItem

@Entity
public class OrderItem {
    @Id
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    private Order order;
    
    @ManyToOne(fetch = FetchType.LAZY)
    private Product product;
 
}

Product

@Entity
public class Product {
    @Id
    private Long id;
    
    private String name;

}

OrderRepository

@Repository
public class OrderRepository {

    @Autowired
    private EntityManager entityManager;
    
    public List<Order> findAllOrders() {
        String jpql = "select o from Order o";
       return entityManager.createQuery(jpql, Order.class)
        .getResultList();
        
    }
}

N+1๋ฌธ์ œ ๋ฐœ์ƒ

List<Order> orders = orderRepository.findAllOrders();

for (Order order : orders) {
    List<OrderItem> orderItems = order.getOrderItems(); // N+1 ๋ฌธ์ œ ๋ฐœ์ƒ
}

๐Ÿ˜ฐn+1์ด ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ๋กœ๋Š” ๋จผ์ € orderRepository๋ฅผ ํ†ตํ•ด order๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๋ฉด repository๋Š” order๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ ์ด ๋•Œ order์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹Œ lazy๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š” ๊ฐ’์—๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๋„ฃ์–ด ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.
๐Ÿ˜ข์ด๋กœ ์ธํ•ด order๊ฐ์ฒด ์•ˆ์— lazy๋กœ ์„ค์ •๋œ ๊ฐ’์—๋Š” ์‹ค์ œ ๊ฐ’์ด ๋“ค์–ด์žˆ์ง€ ์•Š๊ณ  ํ˜ธ์ถœ ๋˜์—ˆ์„ ๋•Œ ์‹ค์ œ ๊ฐ’์„ ๋‹ค์‹œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜๋Š”๋ฐ ์ด ๋•Œ ์ฒ˜์Œ 1๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆผ์œผ๋กœ์จ ํ›„์— N๋ฒˆ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋˜ ๋‹ค์‹œ ๋‚ ๋ผ๊ฐ€๊ฒŒ ๋œ๋‹ค๊ณ  ํ•˜์—ฌ N+1๋ฌธ์ œ๋ผ๊ณ  ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ ํ•˜์—ฌํ– ํ•˜๋Š”๊ฐ€?

๐Ÿ˜Ž๋ฐ”๋กœ fetch join์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค.

@Repository
public class OrderRepository {
    @PersistenceContext
    private EntityManager entityManager;
    
    public List<Order> findAllOrders() {
        String jpql = "select o from Order o join fetch o.orderItems oi join fetch oi.product";
        return entityManager.createQuery(jpql, Order.class).getResultList();
        
    }
}

๐Ÿ˜Š์œ„์™€ ๊ฐ™์ด ๋งŒ์•ฝ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ๋•Œ ๋ชจ๋“  ๊ฐ’์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด fetch join์„ ํ†ตํ•ด ๋ชจ๋‘ ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค. ๋งŒ์•ฝ fetch join์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹ซ๋‹ค๋ฉด @BatchSize ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•˜์—ฌ N๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ์ง€ ์•Š๊ณ  ์ตœ์ ํ™”ํ•˜์—ฌ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

profile
greenTea์ž…๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€