جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی


در این بخش نگاهی میکنیم به انواع FetchMode که در org.hibernate.annotations.Fetch@ استفاده میکنیم 



ساخت Entity نمونه :


@Entity
public class Customer {
 
    @Id
    @GeneratedValue
    private Long id;
 
    @OneToMany(mappedBy = "customer")
    @Fetch(value = FetchMode.SELECT)
    private Set<Order> orders = new HashSet<>();
 
    // getters and setters
}


@Entity
public class Order {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String name;
 
    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;
 
    // getters and setters
}


به روابط بین کلاس Customer و Order توجه کنید به ازای هر Customer میتوان چندین Order داشت 

در ادامه مثال ها ما قرار است Customer ها را همراه با Order هایشان دریافت کنیم :


Customer customer = customerRepository.findById(id).get();
Set<Order> orders = customer.getOrders();




FetchMode.SELECT :


در Customer entity ما فیلد orders را با (Fetch(FetchMode.SELEC@ مشخص کرده ایم 

@OneToMany
@Fetch(FetchMode.SELECT)
private Set<Orders> orders;


* ما با استفاده از Fetch@ به hibernate مشخص میکنیم هایبرنیت چگونه موقعی که یک Customer را دریافت میکند چگونه باید orders را دریافت کند و استفاده از FetchMode.SELECT نوع Fetch را از نوع LAZY تعیین میکند


Customer customer = customerRepository.findById(id).get();


وقتی اجرا میکنیم هیچ Join ای با جدول Order نمیبینیم :


Hibernate: 
    select ...from customer
    where customer0_.id=?


بعد برای دریافت Orders در خط بعدی :

Set<Order> orders = customer.getOrders();


کوئری مربوط به Orders بدین صورت زده میشود :


Hibernate: 
    select ...from order
    where order0_.customer_id=?


در اینجا میبینیم که وقتی FetchMode.SELECT تعیین شده باشد هایبرنیت بعد از کوئری اول زمانی که نیاز به لود شدن orders بود کوئری جداگانه ای میزند

در این مثال یک کوئری برای دریافت لیست Customer ها و 5 کوئری برای دریافت مجموعه Order ها زده میشود

مشکل شناخته شده n + 1 select problem مشهود است یعنی به ازای هر یک کوئری n کوئری اضافی در بر خواهد داشت





BatchSize@ :


در کنار FetchMode.SELECT میتوان از BatchSize@ هم استفاده کرد در این صورت هایبرنیت سعی میکند مجموعه orders را با batch size تعیین شده لود کند


@OneToMany
@Fetch(FetchMode.SELECT)
@BatchSize(size=10)
private Set<Orders> orders;


در این مثال چون ما 5 orders داریم یک کوئری کافی است و میتوانیم همان یک کوئری قبل را ببینیم :


Hibernate:
    select ...from order
    where order0_.customer_id=?


اما برای دریافت مجموعه orders یک کوئری دیگر خواهد خورد و مسئله n + 1 select problem را دیگر نداریم 





FetchMode.JOIN :


در حالی که FetchMode.SELECT روابط ها را بصورت LAZY لود میکند استفاده از FetchMode.JOIN آنها را بصورت EAGER لود خواهد کرد 


@OneToMany
@Fetch(FetchMode.JOIN)
private Set<Orders> orders;


چون لود از نوع EAGER است میتوانیم Join خوردن دو جدول را در کوئری مشاهده کنیم :


Hibernate: 
    select ...
    from
        customer customer0_ 
    left outer join
        order order1 
            on customer.id=order.customer_id 
    where
        customer.id=?





FetchMode.SUBSELECT :


چون فیلد orders بصورت Colelction است ما همچنین میتوانیم از FetchMode.SUBSELECT استفاده کنیم که تنها روی Collection ها قابل استفاده است :


@OneToMany
@Fetch(FetchMode.SUBSELECT)
private Set<Orders> orders;


کوئری Customer :

Hibernate: 
    select ...
    from customer customer0_


کوئری دوم برای Orders که با sub-select همراه است  : 


Hibernate: 
    select ...
    from
        order order0_ 
    where
        order0_.customer_id in (
            select
                customer0_.id 
            from
                customer customer0_
        )







فرق بین FetchType و FetchMode :


با استفاده از FetchMode هایبرنیت تعیین میکند که دیتا چگونه با select , subselect و join لود شود ولی با استفاده از FetchType تنها مشخص میکنیم که دیتا بصورت EAGE یا LAZY لود شود 


و اگر ترکیبی از آنها استفاده شود شرایط زیر پیش خواهد آمد :


- اگر در کد FetchMode ای تعیین نشده باشد پیش فرض روی JOIN است و FetchType همانگونه که تعریف شده کار خواهد کرد 

- اگر FetchMode.SELECT و FetchMode.SUBSELECT ست شده باشد FetchType همانگونه که تعریف شده کار خواهد کرد 

- وقتی FetchMode.JOIN ست شده باشد FetchType نادیده گرفته میشود و کوئری بصورت EAGER لود خواهد شد 









نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی