จาก API ฉันเห็นว่ามันเกี่ยวข้องกับพร็อกซี แต่ฉันไม่พบข้อมูลมากมายเกี่ยวกับพร็อกซีและไม่เข้าใจความแตกต่างระหว่างการโทรsession.get
และsession.load
. ใครช่วยอธิบายหรือนำฉันไปที่หน้าอ้างอิงได้ไหม
ขอขอบคุณ!!
จาก API ฉันเห็นว่ามันเกี่ยวข้องกับพร็อกซี แต่ฉันไม่พบข้อมูลมากมายเกี่ยวกับพร็อกซีและไม่เข้าใจความแตกต่างระหว่างการโทรsession.get
และsession.load
. ใครช่วยอธิบายหรือนำฉันไปที่หน้าอ้างอิงได้ไหม
ขอขอบคุณ!!
คำตอบ:
จากฟอรัม Hibernate :
จากหนังสือ Hibernate in Action น่าอ่าน ..
การดึงอ็อบเจ็กต์ด้วยตัวระบุข้อมูลโค้ดไฮเบอร์เนตต่อไปนี้ดึงอ็อบเจ็กต์ผู้ใช้จากฐานข้อมูล:
User user = (User) session.get(User.class, userID);
เมธอด get () เป็นวิธีพิเศษเนื่องจากตัวระบุระบุอินสแตนซ์ของคลาสเดียวโดยไม่ซ้ำกัน ดังนั้นจึงเป็นเรื่องปกติที่แอปพลิเคชันจะใช้ตัวระบุเป็นตัวจัดการที่สะดวกสำหรับวัตถุถาวร การดึงข้อมูลด้วยตัวระบุสามารถใช้แคชเมื่อดึงอ็อบเจ็กต์หลีกเลี่ยงการโดนฐานข้อมูลหากอ็อบเจ็กต์ถูกแคชไว้แล้ว ไฮเบอร์เนตยังมีวิธี load ():
User user = (User) session.load(User.class, userID);
วิธี load () เก่ากว่า get () ถูกเพิ่มใน API ของ Hibernate เนื่องจากคำขอของผู้ใช้ ความแตกต่างเป็นเรื่องเล็กน้อย:
ถ้า load () ไม่พบวัตถุในแคชหรือฐานข้อมูลจะมีข้อยกเว้น วิธี load () ไม่คืนค่า null เมธอด get () จะคืนค่า null หากไม่พบวัตถุ
วิธี load () อาจส่งคืนพร็อกซีแทนที่จะเป็นอินสแตนซ์ถาวรจริง พร็อกซีคือตัวยึดตำแหน่งที่ทริกเกอร์การโหลดอ็อบเจ็กต์จริงเมื่อเข้าถึงเป็นครั้งแรก ในทางกลับกัน get () ไม่ส่งคืนพร็อกซี การเลือกระหว่าง get () และ load () เป็นเรื่องง่าย: หากคุณมั่นใจว่ามีออบเจ็กต์ถาวรอยู่และการไม่มีอยู่จะถือว่าเป็นสิ่งพิเศษ load () เป็นตัวเลือกที่ดี หากคุณไม่แน่ใจว่ามีอินสแตนซ์ถาวรพร้อมตัวระบุที่กำหนดให้ใช้ get () และทดสอบค่าที่ส่งคืนเพื่อดูว่าเป็นโมฆะหรือไม่ การใช้ load () มีความหมายเพิ่มเติม: แอปพลิเคชันอาจดึงข้อมูลอ้างอิงที่ถูกต้อง (พร็อกซี) ไปยังอินสแตนซ์แบบถาวรโดยไม่ต้องกดปุ่มฐานข้อมูลเพื่อดึงข้อมูลสถานะถาวร ดังนั้น load () อาจไม่ทำให้เกิดข้อยกเว้นเมื่อไม่พบวัตถุถาวรในแคชหรือฐานข้อมูล ข้อยกเว้นจะถูกโยนทิ้งในภายหลังเมื่อมีการเข้าถึงพร็อกซี แน่นอนว่าการดึงวัตถุด้วยตัวระบุนั้นไม่ยืดหยุ่นเท่ากับการใช้การสืบค้นตามอำเภอใจ
อย่างน้อยที่สุดใน nhibernate session get (id) จะโหลดอ็อบเจ็กต์จากฐานข้อมูลในขณะที่ session.Load (id) จะสร้างพร็อกซีอ็อบเจ็กต์เท่านั้นโดยไม่ต้องออกจากเซิร์ฟเวอร์ของคุณ ทำงานเหมือนกับคุณสมบัติที่โหลดแบบขี้เกียจอื่น ๆ ใน POCO ของคุณ (หรือ POJOs :) จากนั้นคุณสามารถใช้พร็อกซีนี้เป็นการอ้างอิงถึงออบเจ็กต์เพื่อสร้างความสัมพันธ์ ฯลฯ
คิดว่ามันเหมือนกับมีวัตถุที่เก็บเฉพาะ Id และจะโหลดส่วนที่เหลือหากคุณต้องการ หากคุณเพียงแค่ผ่านมันไปรอบ ๆ เพื่อสร้างความสัมพันธ์ (เช่น FKs) id คือสิ่งที่คุณต้องการ
session.load () จะส่งคืน "พร็อกซี" (คำไฮเบอร์เนต) เสมอโดยไม่ต้องกดปุ่มฐานข้อมูล ใน Hibernate พร็อกซีคืออ็อบเจกต์ที่มีค่าตัวระบุที่กำหนดคุณสมบัติของมันยังไม่ได้ถูกเตรียมใช้งาน แต่ดูเหมือนเป็นวัตถุปลอมชั่วคราว หากไม่พบแถวก็จะพ่น ObjectNotFoundException
session.get () ตีฐานข้อมูลและส่งคืนวัตถุจริงเสมอซึ่งเป็นวัตถุที่แสดงแถวฐานข้อมูลไม่ใช่พร็อกซี หากไม่พบแถวจะส่งคืนค่าว่าง
ประสิทธิภาพด้วยวิธีการเหล่านี้ยังสร้างความแตกต่าง ระหว่างสอง ...
อีกหนึ่งจุดพิเศษ ::
รับเมธอดของคลาส Hibernate Session จะคืนค่า null หากไม่พบอ็อบเจ็กต์ในแคชและบนฐานข้อมูล ในขณะที่วิธี load () จะพ่น ObjectNotFoundException หากไม่พบอ็อบเจ็กต์บนแคชและบนฐานข้อมูล แต่ไม่ส่งคืนค่าว่าง
ผลทางอ้อมอย่างหนึ่งของการใช้ "load" แทน "get" คือการล็อกการมองโลกในแง่ดีโดยใช้แอตทริบิวต์ version อาจไม่ได้ผลตามที่คุณคาดหวัง หากการโหลดเพียงสร้างพร็อกซีและไม่ได้อ่านจากฐานข้อมูลคุณสมบัติเวอร์ชันจะไม่ถูกโหลด เวอร์ชันจะโหลดก็ต่อเมื่อ / หากคุณอ้างถึงคุณสมบัติบนวัตถุในภายหลังโดยเรียกใช้การเลือก ในระหว่างนี้เซสชันอื่นสามารถอัปเดตออบเจ็กต์ได้และเซสชันของคุณจะไม่มีเวอร์ชันดั้งเดิมที่จำเป็นต้องทำการตรวจสอบการล็อกในแง่ดีดังนั้นการอัปเดตเซสชันของคุณจะเขียนทับการอัปเดตของเซสชันอื่นโดยไม่มีคำเตือน
นี่คือความพยายามในการร่างสถานการณ์นี้โดยมีสองเซสชันที่ทำงานกับออบเจ็กต์ที่มีตัวระบุเดียวกัน เวอร์ชันเริ่มต้นสำหรับอ็อบเจ็กต์ใน DB คือ 10
Session 1 Session 2
--------- ---------
Load object
Wait a while..
Load object
Modify object property
[triggers db 'select' -
version read as 10]
Commit
[triggers db update,
version modified to 11]
Modify object property
[triggers db 'select' -
version read as 11]
Commit
[triggers db update,
version modified to 12]
จริงๆแล้วเราต้องการให้การกระทำของเซสชัน 1 ล้มเหลวด้วยข้อยกเว้นการล็อกในแง่ดี แต่จะสำเร็จที่นี่
การใช้ "get" แทน "load" จะช่วยแก้ปัญหาได้เนื่องจาก get จะออกการเลือกทันทีและหมายเลขเวอร์ชันจะถูกโหลดตามเวลาที่ถูกต้องสำหรับการตรวจสอบการล็อกในแง่ดี
นอกจากนี้เราต้องระมัดระวังในขณะที่ใช้โหลดเนื่องจากจะทำให้เกิดข้อยกเว้นหากไม่มีวัตถุ เราต้องใช้ก็ต่อเมื่อแน่ใจว่ามีวัตถุนั้นอยู่
ดูคำอธิบายที่ยอดเยี่ยมได้ที่http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load ():
มันจะส่งคืน "พร็อกซี" (คำไฮเบอร์เนต) เสมอโดยไม่ กดปุ่มฐานข้อมูล
ใน Hibernate พร็อกซีคืออ็อบเจกต์ที่มีค่าตัวระบุที่กำหนดคุณสมบัติของมันยังไม่ได้ถูกเตรียมใช้งาน แต่ดูเหมือนเป็นวัตถุปลอมชั่วคราว
มันจะส่งคืนอ็อบเจ็กต์พร็อกซีพร้อมกับค่าเอกลักษณ์ที่กำหนดเสมอแม้ค่าเอกลักษณ์จะไม่มีอยู่ในฐานข้อมูล อย่างไรก็ตามเมื่อคุณพยายามเริ่มต้นพร็อกซีโดยดึงคุณสมบัติจากฐานข้อมูลมันจะเข้าสู่ฐานข้อมูลด้วยคำสั่งที่เลือก หากไม่พบแถว ObjectNotFoundException จะโยน
session.get ():
มันจะเข้าสู่ฐานข้อมูลเสมอ (หากไม่พบในแคช) และส่งคืนวัตถุจริงซึ่งเป็นวัตถุที่แสดงแถวฐานข้อมูลไม่ใช่พร็อกซี
หากไม่พบแถวจะส่งคืนค่าว่าง
load () ไม่พบวัตถุจากแคชหรือฐานข้อมูลมีข้อยกเว้นเกิดขึ้นและวิธี load () จะไม่คืนค่า null
get () วิธีการคืนค่า null ถ้าไม่พบวัตถุ วิธี load () อาจส่งคืนพร็อกซีแทนอินสแตนซ์ถาวรจริง get () ไม่ส่งคืนพร็อกซี