การโหลดแบบขี้เกียจในไฮเบอร์เนตคืออะไร


178

การโหลดขี้เกียจใน Java คืออะไร ฉันไม่เข้าใจกระบวนการ ใครช่วยให้ฉันเข้าใจกระบวนการขี้เกียจโหลดได้หรือไม่

คำตอบ:


268

สมมติว่าคุณมีผู้ปกครองและผู้ปกครองนั้นมีคอลเลกชันของเด็ก ๆ ตอนนี้ไฮเบอร์เนตสามารถ "lazy-load" children ได้ซึ่งหมายความว่าไม่ได้โหลด children ทั้งหมดเมื่อโหลดพาเรนต์ แต่จะโหลดเมื่อมีการร้องขอ คุณสามารถร้องขอสิ่งนี้ได้อย่างชัดเจนหรือและนี่เป็นเรื่องธรรมดามากที่ไฮเบอร์เนตจะโหลดโดยอัตโนมัติเมื่อคุณพยายามเข้าถึงเด็ก

การโหลดขี้เกียจสามารถช่วยปรับปรุงประสิทธิภาพได้อย่างมีนัยสำคัญเนื่องจากบ่อยครั้งที่คุณไม่ต้องการใช้ลูกดังนั้นจึงไม่โหลด

นอกจากนี้ระวังปัญหา n + 1 ด้วย ไฮเบอร์เนตจะไม่โหลดเด็กทั้งหมดเมื่อคุณเข้าถึงคอลเลกชัน แต่จะโหลดเด็กแต่ละคนแยกกัน เมื่อวนซ้ำคอลเลกชันสิ่งนี้จะทำให้แบบสอบถามสำหรับเด็กทุกคน เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถหลอกให้จำศีลในการโหลดเด็กทุกคนพร้อมกันเช่นโดยการเรียก parent.getChildren (). size ()


5
ควรใช้ Hibernate.initialize (parent.getChildren ())
HakunaMatata

18
คำสั่ง "เมื่อคุณเข้าถึงคอลเลกชัน ... มันจะโหลดเด็กแต่ละคนเป็นรายบุคคล" จริง ๆ แล้วไม่ถูกต้องสมบูรณ์ มันตรงกันข้ามจริง ๆ dereference ใด ๆ ของ parent.getChildren () จะทำให้ Hibernate โหลดลูกทั้งหมดในการรวบรวมในหนึ่งแบบสอบถาม db ยกเว้นว่าคุณใช้คำแนะนำการโหลดแบบขี้เกียจ "พิเศษขี้เกียจ" พิเศษมาก หรือถ้าคุณไม่เก็บแคชในแคชระดับที่สองและเด็ก ๆ ที่เกี่ยวข้องจะไม่ถูกแคช
Steve Ebersole

โอ้มากเกินไป Stack - คำตอบที่ดีที่สุดที่จะพบที่ด้านล่างของหน้า ;-)
Piotrek Hryciuk

76

"โหลดขี้เกียจ" หมายความว่าองค์กรจะถูกโหลดเพียงเมื่อคุณจริงเข้าถึงนิติบุคคลสำหรับครั้งแรกเวลา

รูปแบบที่เป็นเช่นนี้

public Entity getEntity() {
    if (entity == null) {
        entity = loadEntity();
    }
    return entity;
}

นี้ช่วยประหยัดค่าใช้จ่ายของการพรีโหลด / กำลังเติมล่วงหน้าทุกหน่วยงานในชุดข้อมูลที่มีขนาดใหญ่ก่อนในขณะที่คุณหลังจากทั้งหมดจริงไม่จำเป็นต้องทั้งหมดของพวกเขา

ใน Hibernate คุณสามารถกำหนดค่าให้โหลดชุดเอนทิตีชายน์อย่างเกียจคร้านได้ จริงโหลดขี้เกียจจะทำแล้วภายในวิธีการที่PersistentSetซึ่งใช้ Hibernate "ภายใต้หมวก" Setการที่จะกำหนดให้คอลเลกชันของหน่วยงานเป็น

เช่น

public class Parent {
    private Set<Child> children;

    public Set<Child> getChildren() {
        return children;
    }
}

.

public void doSomething() {
    Set<Child> children = parent.getChildren(); // Still contains nothing.

    // Whenever you call one of the following (indirectly), 
    // Hibernate will start to actually load and fill the set.
    children.size();
    children.iterator();
}

25

Martin Fowler กำหนดรูปแบบLazy Loadในรูปแบบของสถาปัตยกรรมแอปพลิเคชันองค์กรเช่น:

วัตถุที่ไม่มีข้อมูลทั้งหมดที่คุณต้องการ แต่รู้วิธีที่จะได้รับ

ดังนั้นเมื่อโหลดวัตถุที่กำหนดความคิดคือไม่อยากโหลดวัตถุที่เกี่ยวข้องที่คุณไม่สามารถใช้งานได้ทันทีเพื่อประหยัดต้นทุนประสิทธิภาพที่เกี่ยวข้อง แต่วัตถุที่เกี่ยวข้องจะถูกโหลดเมื่อใช้งานเท่านั้น

นี่ไม่ใช่รูปแบบเฉพาะสำหรับการเข้าถึงข้อมูลและไฮเบอร์เนต แต่มีประโยชน์อย่างยิ่งในฟิลด์ดังกล่าวและไฮเบอร์เนตรองรับการโหลดการเชื่อมโยงแบบหนึ่งต่อหลายและการเชื่อมโยงแบบจุดเดียว (ขี้เกียจ) และแบบหนึ่งต่อหนึ่ง ภายใต้เงื่อนไขบางประการ รายละเอียดเพิ่มเติมในบทที่ 19ของเอกสารอ้างอิงอ้างอิง Hibernate 3.0


15

Bydefault lazy loading เป็น true.Lazy loading หมายถึงเมื่อดำเนินการแบบสอบถามแบบใช้เลือกข้อมูลนั้นจะไม่เกิดผลกับฐานข้อมูล มันจะรอฟังก์ชั่น getter เช่นเมื่อเราต้องการมันจะดึงข้อมูลจากดาต้าเบส ตัวอย่างเช่นคุณเป็นผู้ปกครองที่มีเด็กที่มีของเล่นมากมาย แต่ปัญหาในปัจจุบันคือเมื่อใดก็ตามที่คุณเรียกเขาว่า (เราสมมติว่าคุณมีเด็กผู้ชาย) เขามาหาคุณพร้อมกับของเล่นทั้งหมดของเขาเช่นกัน ตอนนี้เป็นปัญหาเนื่องจากคุณไม่ต้องการให้เขาอุ้มของเล่นของเขาตลอดเวลา ดังนั้นการเป็นผู้ปกครองเหตุผลคุณไปข้างหน้าและกำหนดของเล่นของเด็กเป็นขี้เกียจ ตอนนี้เมื่อใดก็ตามที่คุณโทรหาเขาเขาจะมาหาคุณโดยไม่มีของเล่นของเขา


11

การดึงข้อมูล Lazy ตัดสินใจว่าจะโหลดวัตถุลูกขณะโหลดวัตถุแม่หรือไม่ คุณต้องทำการตั้งค่าไฟล์การจำศีลตามลำดับของคลาสพาเรนต์ Lazy = true(หมายถึงไม่ให้โหลดลูก) โดยค่าเริ่มต้นการโหลดวัตถุวัตถุลูกนั้นจะเป็นความจริง

สิ่งนี้ทำให้แน่ใจว่าวัตถุลูกไม่ได้ถูกโหลดเว้นแต่พวกมันจะถูกเรียกอย่างชัดเจนในแอพพลิเคชั่นโดยการเรียกgetChild()วิธีการกับผู้ปกครองในกรณีนี้ไฮเบอร์เนตจะเรียกการเรียกฐานข้อมูลใหม่เพื่อโหลดเด็กเมื่อgetChild()ถูกเรียกใช้บนวัตถุแม่

แต่ในบางกรณีคุณจำเป็นต้องโหลดวัตถุลูกเมื่อโหลดแม่ เพียงแค่ทำให้ lazy = false และ hibernate จะโหลดลูกเมื่อแม่ถูกโหลดจากฐานข้อมูล

ตัวอย่าง: ถ้าคุณมีตาราง พนักงานจับคู่กับวัตถุของพนักงานและมีชุดของวัตถุที่อยู่ คลาสหลัก: คลาสพนักงาน, คลาสย่อย: คลาสที่อยู่

public class Employee { 
private Set address = new HashSet(); // contains set of child Address objects 
public Set getAddress () { 
return address; 
} 
public void setAddresss(Set address) { 
this. address = address; 
} 
} 

ในไฟล์ Employee.hbm.xml

<set name="address" inverse="true" cascade="delete" lazy="false"> 
<key column="a_id" /> 
<one-to-many class="beans Address"/> 
</set> 

ในการกำหนดค่าข้างต้น ถ้าlazy="false": - เมื่อคุณโหลดออบเจ็กต์พนักงานในขณะนั้นที่อยู่ออบเจ็กต์ลูกจะถูกโหลดและตั้งค่าเป็นเมธอด setAddresss () ถ้าคุณโทร employee.getAdress () ดังนั้นข้อมูลที่โหลดกลับมาจะไม่มีการเรียกฐานข้อมูลใหม่

ถ้าlazy="true": - นี่คือการกำหนดค่าเริ่มต้น ถ้าคุณไม่พูดถึงก็จำศีลพิจารณาว่าขี้เกียจ = จริง เมื่อคุณโหลดวัตถุพนักงานที่วัตถุลูกเวลาที่อยู่ไม่ได้โหลด คุณต้องมีการโทรพิเศษไปยังฐานข้อมูลเพื่อรับวัตถุที่อยู่ ถ้าคุณเรียกใช้employee.getAdress()แบบสอบถามฐานข้อมูลเวลานั้นจะยิงและส่งคืนผลลัพธ์ การเรียกฐานข้อมูลใหม่


พนักงานและที่อยู่ไม่มีความสัมพันธ์พ่อแม่และลูกในสถานการณ์นี้ มันคือความสัมพันธ์แบบ 'มี - a' !
ราม

นี่คือการรวมไม่ใช่การสืบทอด
ฤishiษี

11

ในภาษาของคนธรรมดามันเหมือนกับว่าคุณกำลังทำเค้กและคุณจะต้องใช้ส่วนผสม 5-10 อย่างจากตู้เย็น คุณมีสองตัวเลือกรับส่วนผสมทั้งหมดจากตู้เย็นและวางไว้บนแพลตฟอร์มห้องครัวของคุณหรือนำรายการที่คุณต้องการเมื่อคุณต้องการ

ในทำนองเดียวกันในการโหลดกระตือรือร้นคุณดึงข้อมูลทั้งหมดเกี่ยวกับถั่วและชั้นเรียนที่เกี่ยวข้อง (ไม่ใช่ลูกหรือเป็นความสัมพันธ์ แต่มีความสัมพันธ์เช่นเค้กมีแป้งมีนมมีครีม ฯลฯ ) และในกรณีที่โหลดขี้เกียจก่อน คุณนำเฉพาะตัวบ่งชี้และค่านิยมที่มาจากตารางเดียวกัน (ส่วนผสมที่จำเป็นซึ่งคุณต้องใช้ในชามเค้กก่อน) ข้อมูลทั้งหมดที่มาจากตารางอื่น ๆ จะถูกดึงมาเป็นและเมื่อจำเป็น / ใช้


8

กำลังโหลดขี้เกียจ? หมายความว่าระเบียนของเด็กจะไม่ถูกดึงออกมาทันที แต่โดยอัตโนมัติทันทีที่คุณพยายามเข้าถึง


4

การโหลดแบบ Lazy ช่วยให้คุณเลื่อนการดึงการเชื่อมโยงหรือควบคุมการดึงข้อมูลกลยุทธ์ได้ดีขึ้น

เมื่อคุณใช้การโหลด EAGER คุณกำหนดแผนการดึงข้อมูลทั่วโลกซึ่งไม่สามารถเขียนทับได้ในเวลาสืบค้นซึ่งหมายความว่าคุณ จำกัด การตัดสินใจของคุณในขณะที่ออกแบบโมเดลเอนทิตีของคุณ การดึงข้อมูลของ EAGER เป็นกลิ่นรหัสเนื่องจากกลยุทธ์การดึงข้อมูลเป็นนโยบายเวลาสืบค้นและอาจแตกต่างจากกรณีการใช้งานทางธุรกิจไปยังอีกกรณีหนึ่ง

กลยุทธ์การดึงข้อมูลเป็นสิ่งสำคัญมากในขณะที่กำลังนำเกินไปกระตือรือร้นมากอาจทำให้เกิดปัญหาประสิทธิภาพการทำงานที่เกี่ยวข้องอย่างจริงจัง


3

การตั้งค่า Lazy ตัดสินใจว่าจะโหลดวัตถุลูกในขณะที่โหลดวัตถุหลักหรือไม่คุณต้องทำการตั้งค่าไฟล์การทำแผนที่จำศีลตามลำดับของคลาสผู้ปกครอง Lazy = true (หมายถึงไม่โหลดเด็ก) โดยค่าเริ่มต้นการโหลดวัตถุวัตถุลูกนั้นเป็นจริง . สิ่งนี้ทำให้แน่ใจว่าวัตถุลูกไม่ได้ถูกโหลดเว้นแต่พวกมันจะถูกเรียกอย่างชัดเจนในแอพพลิเคชั่นโดยเรียกเมธอด getChild () บนพาเรนต์ในกรณีนี้ไฮเบอร์เนตจะเรียกใช้ฐานข้อมูลใหม่เพื่อโหลดเด็กเมื่อ getChild () วัตถุ แต่ในบางกรณีคุณจำเป็นต้องโหลดวัตถุลูกเมื่อโหลดแม่ เพียงแค่ทำให้ lazy = false และ hibernate จะโหลดลูกเมื่อมีการโหลดพาเรนต์จากฐานข้อมูล Exampleslazy = true (ค่าเริ่มต้น) แอดเดรสลูกของคลาสผู้ใช้สามารถทำให้ขี้เกียจหากไม่จำเป็นต้องใช้บ่อย


2

Lazy loading เป็นรูปแบบการออกแบบที่ใช้กันทั่วไปในการเขียนโปรแกรมคอมพิวเตอร์เพื่อเลื่อนการเริ่มต้นของวัตถุจนกระทั่งถึงจุดที่ต้องการ มันสามารถช่วยเพิ่มประสิทธิภาพในการทำงานของโปรแกรมหากใช้อย่างเหมาะสมและเหมาะสม

วิกิพีเดีย

ลิงค์ของLazy Loadingจาก hibernate.org


1

มันก็หมายถึงการโหลดข้อมูลที่คุณต้องการในปัจจุบันแทนที่จะโหลดทั้งกลุ่มในคราวเดียวซึ่งคุณจะไม่ใช้ตอนนี้ ทำให้ความเร็วในการโหลดแอปพลิเคชันเร็วกว่าปกติ


0

Hiberante รองรับคุณสมบัติของการเริ่มต้นขี้เกียจสำหรับเอนทิตีและคอลเลกชัน เอ็นจินไฮเบอร์เนตโหลดเฉพาะวัตถุเหล่านั้นที่เรากำลังสอบถามไม่ได้รับสิทธิ์หรือคอลเลกชันอื่น ๆ

สันหลังยาว = "false" โดยค่าเริ่มต้นการโหลดเริ่มต้นพูดถึงสำหรับเด็กเพียงคนเดียวคือกรณี lazy.in ของจริงที่เป็นผู้ปกครองกำลังโหลดไม่สนับสนุนเด็ก


0

การตั้งค่า Lazy ตัดสินใจว่าจะโหลดวัตถุลูกในขณะที่โหลดวัตถุหลักหรือไม่คุณต้องทำการตั้งค่าไฟล์การทำแผนที่จำศีลตามลำดับของคลาสผู้ปกครอง Lazy = true (หมายถึงไม่โหลดเด็ก) โดยค่าเริ่มต้นการโหลดวัตถุวัตถุลูกนั้นเป็นจริง .


0

น่าแปลกที่ไม่มีคำตอบพูดคุยเกี่ยวกับวิธีที่จะประสบความสำเร็จโดยจำศีลหลังหน้าจอ

การโหลดแบบ Lazyเป็นรูปแบบการออกแบบที่ใช้อย่างมีประสิทธิภาพในโหมดไฮเบอร์เนตด้วยเหตุผลด้านประสิทธิภาพซึ่งเกี่ยวข้องกับเทคนิคต่อไปนี้


1. การวัดรหัสไบต์ :

ปรับปรุงนิยามคลาสพื้นฐานด้วยhooks hibernate เพื่อสกัดกั้นการเรียกทั้งหมดไปยังวัตถุเอนทิตีนั้น

ทำได้ทั้งในเวลารวบรวมหรือเรียกใช้เวลา [โหลด]

1.1 เวลารวบรวม

  • โพสต์การดำเนินการรวบรวมเวลา

  • ส่วนใหญ่เป็นปลั๊กอิน maven / ant

1.2 เวลาทำงาน

  • หากไม่มีการทำเครื่องมือเวลาคอมไพล์สิ่งนี้จะถูกสร้างขึ้น ณ รันไทม์การใช้ไลบรารีเช่นjavassist

2. ผู้รับมอบฉันทะ

วัตถุเอนทิตีที่ส่งกลับไฮเบอร์เนตเป็นพร็อกซีของประเภทจริง

ดูเพิ่มเติม: Javassist แนวคิดหลักและที่ใช้งานจริงคืออะไร?

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.