ประเภทการดึงข้อมูลเริ่มต้นสำหรับหนึ่งต่อหนึ่งหลายต่อหนึ่งและหนึ่งต่อหลายในไฮเบอร์เนต


104

ประเภทการดึงข้อมูลเริ่มต้นในการแมปไฮเบอร์เนตคืออะไร

สิ่งที่ฉันต้องรู้หลังจากสำรวจคือ:

  • อย่างใดอย่างหนึ่งต่อหนึ่งมันเป็นความกระตือรือร้น
  • อย่างใดอย่างหนึ่งต่อหลายคนมันเป็นขี้เกียจ

แต่หลังจากทดสอบใน Eclipse แล้วก็มีความกระตือรือร้นอย่างมาก

ขึ้นอยู่กับว่าฉันใช้ JPA หรือ Hibernate หรือไม่


1
ในกรณีที่คุณยังคงมีส่วนร่วมในหัวข้อ JPA ฉันอัปเดตคำถามของคุณด้วยคำตอบใหม่เนื่องจากคำถามเก่าล้าสมัยสำหรับเวอร์ชันไฮเบอร์เนตปัจจุบัน
Alexander Rühl

คำตอบ:


194

ขึ้นอยู่กับว่าคุณใช้ JPA หรือ Hibernate

จากข้อมูลจำเพาะ JPA 2.0ค่าเริ่มต้นคือ:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

และในโหมดจำศีลทุกอย่างก็ขี้เกียจ

อัพเดท:

Hibernate เวอร์ชันล่าสุดสอดคล้องกับค่าเริ่มต้น JPA ข้างต้น


11
"และในโหมดจำศีลทุกอย่างก็ขี้เกียจ" เห็นได้ชัดว่ามีการเปลี่ยนแปลงในเวอร์ชันล่าสุด โปรดดูคำตอบของอเล็กซานเด Ruhl ด้านล่าง
Dinei

1
Hibernate เป็นหนึ่งในการใช้งาน JPA ดังนั้นเมื่อคุณใช้ Hibernate คุณจะใช้ JPA :)
xenteros

นี่คือคำค้นหายอดนิยม @Ashish Agarwal ได้โปรดอัปเดตบรรทัดสุดท้ายของคำตอบของคุณ ในโหมดไฮเบอร์เนตตอนนี้มันไม่ได้ขี้เกียจเลย
Saurabh Tiwari

อัปเดตโพสต์เกี่ยวกับพฤติกรรมไฮเบอร์เนตล่าสุด
M Anouti

มีการอัปเดตโดยอ้างว่า eager เป็นประเภทการดึงข้อมูลเริ่มต้นสำหรับทุกการแมปซึ่งได้รับการปรับปรุงใหม่โดยบทที่ 11.3 ทั้งในเอกสาร 5.x ปัจจุบันและ 6.x ไฮเบอร์เนตใหม่ดังนั้นฉันจึงยกเลิกการแก้ไข นอกจากนี้ยังผิดคำแนะนำที่จะไม่มีความกระตือรือร้นโดยอัตโนมัติเนื่องจากอาจหมายถึงการเลือกฐานข้อมูลทั้งหมดเมื่อดึงข้อมูลวัตถุชิ้นเดียว
Alexander Rühl

52

ฉันรู้ว่าคำตอบนั้นถูกต้องในขณะที่ถามคำถาม - แต่เนื่องจากผู้คน (เช่นฉันในนาทีนี้) ยังคงพบว่าพวกเขาสงสัยว่าทำไม WildFly 10 ของพวกเขาถึงมีพฤติกรรมที่แตกต่างกันฉันจึงขออัปเดตสำหรับ Hibernate 5 ปัจจุบัน .x เวอร์ชัน:

ในคู่มือผู้ใช้ Hibernate 5.2มีระบุไว้ในบทที่11.2 การใช้กลยุทธ์การดึงข้อมูล :

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

ดังนั้น Hibernate ก็ทำตัวเหมือน Ashish Agarwal ที่ระบุไว้ข้างต้นสำหรับ JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(ดูข้อมูลจำเพาะ JPA 2.1 )


แล้วถ้าเราใช้เนทีฟไฮเบอร์เนตแทน JPA อิมพ์มันจะทำแบบเดียวกันไหม?
jMounir

@jMounir: ฉันยังไม่ได้ลอง แต่เนื่องจาก Hibernate ระบุว่ามันทำงานเหมือนที่กำหนดไว้ใน JPA ฉันไม่เห็นว่าทำไมมันถึงแตกต่างกันเมื่อใช้ Hibernate สำหรับตัวมันเอง หนึ่งในทั้งสองกรณีสามารถแทนที่กลยุทธ์เริ่มต้น
Alexander Rühl

15

เพื่อตอบคำถามของคุณ Hibernate คือการนำมาตรฐาน JPA มาใช้ Hibernate มีความแปลกใหม่ในการใช้งาน แต่ตามเอกสาร Hibernate

ตามค่าเริ่มต้น Hibernate ใช้การเลือกแบบขี้เกียจสำหรับคอลเลกชันและการดึงข้อมูลพร็อกซีแบบขี้เกียจสำหรับการเชื่อมโยงแบบค่าเดียว ค่าเริ่มต้นเหล่านี้เหมาะสมสำหรับการเชื่อมโยงส่วนใหญ่ในแอปพลิเคชันส่วนใหญ่

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

มันควรจะเข้าใจว่า Hibernate fetchType.EAGERจะพยายามที่จะเติมวัตถุเหล่านี้มีค่าเมื่อคุณพยายามที่จะเข้าถึงวัตถุเว้นแต่คุณจะระบุ


0

สำหรับการเชื่อมโยงที่มีค่าเดียวเช่น-One-to-One และ Many-to-One: -
Default Lazy = proxy proxy
lazy loading : - หมายความว่ามีการโหลดวัตถุพร็อกซีของเอนทิตีที่เกี่ยวข้องของคุณ ซึ่งหมายความว่ามีการโหลดเฉพาะ id ที่เชื่อมต่อทั้งสองเอนทิตีสำหรับวัตถุพร็อกซีของเอนทิตีที่เกี่ยวข้อง
เช่น: A และ B เป็นสองเอนทิตีที่มีการเชื่อมโยงแบบกลุ่มต่อหนึ่ง กล่าวคือ: อาจมี A หลายตัวสำหรับทุกๆ B ทุกออบเจ็กต์ของ A จะมีการอ้างอิงของ B
"

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
ความสัมพันธ์ A จะมีคอลัมน์ (ความช่วยเหลือการเสนอราคา ... คอลัมน์อื่น ๆ ของเอนทิตี A)
ความสัมพันธ์ B จะมีคอลัมน์ (ราคาเสนอ ... คอลัมน์อื่น ๆ ของเอนทิตี B)

พร็อกซีบอกเป็นนัยว่า A ถูกดึงข้อมูลเฉพาะ id เท่านั้นที่ดึงข้อมูลสำหรับ B และเก็บไว้ในวัตถุพร็อกซีของ B ซึ่งมีเฉพาะ id Proxy object ของ B เป็นอ็อบเจ็กต์ของ proxy-class ซึ่งเป็นคลาสย่อยของ B ที่มีฟิลด์เพียงเล็กน้อยเท่านั้น เนื่องจากการเสนอราคาเป็นส่วนหนึ่งของความสัมพันธ์ A อยู่แล้วจึงไม่จำเป็นต้องเริ่มการค้นหาเพื่อรับการเสนอราคาจากความสัมพันธ์ B แอตทริบิวต์อื่น ๆ ของเอนทิตี B จะถูกโหลดอย่างเฉื่อยชาก็ต่อเมื่อมีการเข้าถึงฟิลด์อื่นที่ไม่ใช่ราคาเสนอเท่านั้น

สำหรับคอลเลกชันเช่น-Many-to-Many และ One-to-Many: -
Default Lazy = true


โปรดทราบด้วยว่ากลยุทธ์การดึงข้อมูล (เลือกเข้าร่วม ฯลฯ ) สามารถลบล้างความขี้เกียจได้ เช่น: ถ้า lazy = 'true' และ fetch = 'join' การดึง A จะดึง B หรือ Bs ด้วย (ในกรณีของคอลเลกชัน) คุณจะได้รับเหตุผลถ้าคุณคิดเกี่ยวกับมัน
การดึงค่าเริ่มต้นสำหรับการเชื่อมโยงมูลค่าเดียวคือ "เข้าร่วม"
การดึงคอลเลกชันเริ่มต้นคือ "เลือก" โปรดตรวจสอบสองบรรทัดสุดท้าย ฉันอนุมานได้อย่างมีเหตุผล

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