13 Eylül 2022 Salı

SpringData JpaRepository.findAll() metodu - Kullanmayın

Giriş
findAll() metodu hem JpaRepository hem de CrudRepository tarafından tanımlanıyor. Ata sınıftan gelen metodun imzası şöyle.
Iterable<PaymentMethod> findAll();
Iterable<PaymentMethod> findAll(Sort sort);
Page<PaymentMethod> findAll(Pageable pageable);
1. Neden Anti-Pattern Olabiliyor ?
Tüm veri tabanını findAll() ile getirerek içinde filtreleme yaparak kullanmak bir Anti-Pattern. çekme ihtimali var.

Örnek - Kötü Kullanım
Burada tüm Post nesneleri getiriliyor, daha sonra her Post nesnesinin Tag nesnesi getiriliyor ve tag ismine göre arama yapılıyor. Burada N+1 Select Problem var. bir sürü SQL çalıştırılıyor ve çok verimsiz
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());
Şöyle yaparız. Burada tek bir SQL çalıştırılıyor, dolayısıyla daha verimli
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();
}
2. Yine de Kullanmak İstersek
Örnek - Sort
Şöyle yaparız
Sort sort = Sort.by(Sort.Order.asc("name"),Sort.Order.desc("numberOfHands"));
return personRepository.findAll(sort);
Örnek - Pageable (Aynı Zamanda Sort İşlemini de Yapar)
Pageable yaratmak için PageRequest sınıfı kullanılır. Şöyle yaparız.
Page<Passenger> page = repository.findAll(
  PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));

Hiç yorum yok:

Yorum Gönder