๐คjpa์์ ๊ฐ์ ๊ฐ์ ธ์ฌ๋ fetch type์ Lazy๋ก ์ค์ ํ์๋ค๋ฉด n+1 ๋ฌธ์ ๊ฐ ๋ฐ์ ํ ์ ์๋ค.
@Entity
public class Order {
@Id
private Long id;
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
private List<OrderItem> orderItems;
}
@Entity
public class OrderItem {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Order order;
@ManyToOne(fetch = FetchType.LAZY)
private Product product;
}
@Entity
public class Product {
@Id
private Long id;
private String name;
}
@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();
}
}
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๋ฒ์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ์ง ์๊ณ ์ต์ ํํ์ฌ ๊ฐ์ ธ์ฌ ์ ์๊ฒ ์ค์ ํ ์๋ ์๋ค.