JPA N+1問題について
3350 ワード
JPAを使うといろいろな問題があります
今日はその代表的な問題N+1について解説します.
JpaRepositoryでエンティティのリストを問い合わせると、リストに存在する数に関連付けられたエンティティを問い合わせることができます.
まず、Joinクエリーは予想通りに実行されず、製品クエリーとReviewクエリーがそれぞれ実行されていることがわかります.
ここでは、製品数と同じレビュークエリーが実行されていることがわかります.
なぜこのような問題が発生したのですか?
まず、問題は次のコードに現れます.
JPAのグローバル・フェッチ・ポリシーは、単一のEntityを問合せた場合にのみ有効になります.
「エンティティ」リストをすぐに適用するのではなく、「エンティティ」リストをPersistContextにアップロードします.
適用されます.
したがって、EntityリストがPersistContextにすべてアップロードされ、EAGER fetchポリシーであることを確認してください.
エンティティのリストを表示すると、エンティティのリストに存在するエンティティの関連エンティティが表示されます.
結果はN+1問題を引き起こす.
JPA Queryメソッドを使用する場合
Querydslを使用
Fetch joinはページングクエリを実行しません
今日はその代表的な問題N+1について解説します.
概要
JpaRepositoryでエンティティのリストを問い合わせると、リストに存在する数に関連付けられたエンティティを問い合わせることができます.
@Entity
@Getter
@Table(name = "products")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private long price;
@Getter(AccessLevel.NONE)
@Embedded
private ProductImages productImages;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "product")
private List<Review> reviews;
...
}
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Review {
@Id
private Long id;
@Column(name = "user_id")
private String reviewer;
private String content;
@ManyToOne
private Product product;
...
}
public interface ProductRepository extends JpaRepository<Product, Long> {
}
@SpringBootTest
class ProductRepositoryTest {
@Autowired
ProductRepository productRepository;
@Test
void N_1_문제_테스트() {
// given
Product product_1 = Product.of("product_1", 30000, asList(ProductImage.of("imagePath", 0)));
Product product_2 = Product.of("product_2", 20000, asList(ProductImage.of("imagePath", 0)));
productRepository.save(product_1);
productRepository.save(product_2);
// when
productRepository.findAll();
}
}
まず、Joinクエリーは予想通りに実行されず、製品クエリーとReviewクエリーがそれぞれ実行されていることがわかります.
ここでは、製品数と同じレビュークエリーが実行されていることがわかります.
Why ?
なぜこのような問題が発生したのですか?
まず、問題は次のコードに現れます.
...
public class Product {
...
@OneToMany(fetch = FetchType.EAGER, mappedBy = "product")
private List<Review> reviews;
...
}
この部分を見ると現在のロードポリシーはEAGERロードJPAのグローバル・フェッチ・ポリシーは、単一のEntityを問合せた場合にのみ有効になります.
「エンティティ」リストをすぐに適用するのではなく、「エンティティ」リストをPersistContextにアップロードします.
適用されます.
したがって、EntityリストがPersistContextにすべてアップロードされ、EAGER fetchポリシーであることを確認してください.
エンティティのリストを表示すると、エンティティのリストに存在するエンティティの関連エンティティが表示されます.
結果はN+1問題を引き起こす.
Resolve
Fetch joinの使用
@EntityGraphを使用した位置決め
@BaschSizeノイズの使用
Reference
この問題について(JPA N+1問題について), 我々は、より多くの情報をここで見つけました https://velog.io/@wodyd202/JPA-N-1-문제에-대하여テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol