Giriş
- Eğer ilişki türü LAZY ise FetchMode.SELECT bir sürü SQL çalışmasına sebep oluyor. Bu durumda FetchMode.SUBSELECT kullanılabilir. Açıklaması şöyle.
FetchMode.SUBSELECT is useful as it solves the N+1 query issue of FetchMode.SELECT.
- Eğer ilişki türü - EAGER ise FetchMode.SELECT her bir ilişki için bir select çalıştırılmasına sebep oluyor.
Çalışma Şekli
One tarafı yükleyince Hibernate bu sorguyu hatırlar ve Many tarafı için subselect olarak kullanır. Böylece şu tür kodlar tek bir select ile çalışır
List<Author> authors = authorDataService.findAll(); for (Author author : authors) { ... }
Örnek
Şöyle yaparız. Sadece randevusu olan doktorları yükler.
@Entitypublic class Doctor { ... @OneToMany(mappedBy = "doctor", fetch = FetchType.LAZY) private Collection<Appointment> appointments; } @Entity public class Appointment { ... @JoinColumn(nullable = false) @ManyToOne private Doctor doctor; }
Açıklaması şöyle. Hem sadece randevusu olan doktorları yükler hem de az SQL kullanır.
Hibernate remembers the original query retrieving Doctors and uses it in a subselect to initialize all related Appointments. This way all Doctors in Persistence Context have their Appointments initialized with one additional SQL query visible below.SELECT appointmen0_.doctor_id,appointmen0_.id,appointmen0_.appointmentTime,appointmen0_.doctor_idFROM Appointment appointmen0_WHERE appointmen0_.doctor_id IN (SELECT doctor0_.id FROM Doctor doctor0_)The total number of SQL selects executed by Hibernate with @Fetch annotation is two. First one fetches Doctors and the second one fetches all the Appointments related to already fetched Doctors.
Örnek
Elimizde şöyle bir kod olsun.
@Entitypublic class Author { ... @OneToMany(fetch=FetchType.LAZY, mappedBy="author") private List<Book> books; } @Entity public class Book { ... @ManyToOne private Author author; }
Şu SQL üretilir
select ... from author author0_ select ...from book books0_ where books0_.author_id in (select author0_.id from author author0_)
Örnek
Elimizde şöyle bir kod olsun.
@Entitypublic class Doctor {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@OneToMany(mappedBy = "doctor", fetch = FetchType.LAZY)@org.hibernate.annotations.Fetch(value = FetchMode.SUBSELECT)private Collection<Appointment> appointments;}@Entitypublic class Appointment {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@JoinColumn(nullable = false)@ManyToOneprivate Doctor doctor;}
Şu SQL üretilir
select ... from Appointment appointmen0_where appointmen0_.doctor_id in (select doctor0_.id from Doctor doctor0_)
Elimizde şöyle bir kod olsun.
@Entitypublic class Dept {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@OneToMany(mappedBy = "dept",cascade = CascadeType.ALL,orphanRemoval = true)@Fetch(FetchMode.SUBSELECT)private List<Employee> employees;}@Entitypublic class Employee {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@ManyToOne(fetch = FetchType.LAZY)private Dept dept;}
İlk 10 tane Dept nesnesini şu kodla yükleyelim
final Page<Dept> depts = deptRepository.findAll(pageable);for (Dept dept : depts) {final List<Employee> employees = dept.getEmployees();System.out.println(employees);}
Dept nesneleri yüklenirken şu SQL üretilir
Örnekselect ... from dept dept0_ limit ?select ... from employee employees0_ where employees0_.dept_id in
(select dept0_.id from dept dept0_)
Elimizde şöyle bir kod olsun
@Entity public class Customer { ... @OneToMany(mappedBy = "customer", cascade = CascadeType.PERSIST) @Fetch(FetchMode.SUBSELECT) private Set products; ... } @Entity public class Product { ... @ManyToOne private Customer customer; ... }
SQL şöyle
select ... from product products0 where products0.customerid in ( select customer0.id from customer customer0_ )
Hiç yorum yok:
Yorum Gönder