Parent nesneler yükleniyor ve döngü ile dolaşılıyor. Her parent nesne için child nesneleri çekecek bir SQL çalıştırılır.
Örnek
Şu kodda N+1 problemi ortaya çıkar
@OneToMany(mappedBy = "doctor", fetch = FetchType.LAZY) private Collection<Appointment> appointments;
Örnek
Şu kodda N+1 problemi ortaya çıkar
List<Doctor> doctors = entityManager.createQuery("select d from Doctor d",
Doctor.class)
.getResultList();for (Doctor doctor : doctors) {Assert.assertTrue(doctor.getAppointments().size() > 0);}
Örnek
Şu kodda N+1 problemi ortaya çıkar
List<String> postTitlesStreamRecords = postRepository.findAll() .stream() .filter( post -> post.getTags() .stream() .map(Tag::getName) .anyMatch(matchingTags::contains) ) .sorted(Comparator.comparing(Post::getId)) .map(Post::getTitle) .collect(Collectors.toList())
Çözüm 1
EAGER FETCH yapmak
Çözüm 2
JPQL kullanıyorsak "JOINT FETCH" yapmak. Yani nesne ve ilişkilerini tek seferde yüklemek
JPA JPQL Join yazısına bakabilirsiniz.
Çözüm 3
SQL kullanıyorsak INNER JOIN kullanırız.Şöyle yaparız.
public List<String> findPostTitleByTags(List<String> tags) {
return entityManager.createNativeQuery("""
select p.title
from post p
where exists (
select 1
from post_tag pt
join tag t on pt.tag_id = t.id and pt.post_id = p.id
where t.name in (:tags)
)
order by p.id
""")
.setParameter("tags", tags)
.getResultList();
}
Çözüm 4
@NamedEntityGraph kullanmak
Hiç yorum yok:
Yorum Gönder