เมื่อเรากำลังอัปเดตบันทึกเราสามารถใช้session.flush()
กับไฮเบอร์เนตได้ ต้องการflush()
อะไร?
เมื่อเรากำลังอัปเดตบันทึกเราสามารถใช้session.flush()
กับไฮเบอร์เนตได้ ต้องการflush()
อะไร?
คำตอบ:
การล้างเซสชันจะบังคับให้ไฮเบอร์เนตซิงโครไนซ์สถานะในหน่วยความจำSession
กับฐานข้อมูล (กล่าวคือเพื่อเขียนการเปลี่ยนแปลงในฐานข้อมูล) โดยค่าเริ่มต้นไฮเบอร์เนตจะล้างการเปลี่ยนแปลงโดยอัตโนมัติสำหรับคุณ:
อนุญาตให้ล้างการSession
ควบคุมที่ละเอียดกว่าอย่างชัดเจนที่อาจจำเป็นในบางสถานการณ์ (เพื่อรับ ID ที่กำหนดเพื่อควบคุมขนาดของเซสชัน ... )
id = session.save(obj);
และมีการทำธุรกรรมในบรรทัดถัดไป แต่ obj ไม่ได้รับการบันทึก เป็น DB ทำไม? 2) ฉันบันทึก obj โดยใช้session.save(obj);
กับการกระทำและในขณะที่ส่งคืนฉันใช้return obj.getprimaryID();
ในกรณีนี้ obj จะถูกบันทึกลงใน DB เหตุใดพฤติกรรมนี้จึงเกิดขึ้น?
ดังที่ได้กล่าวไว้อย่างถูกต้องในคำตอบข้างต้นโดยการเรียกflush()
เราบังคับให้ไฮเบอร์เนตดำเนินการคำสั่ง SQL บนฐานข้อมูล แต่เข้าใจว่าการเปลี่ยนแปลงยังไม่ "มุ่งมั่น" ดังนั้นหลังจากทำการล้างและก่อนทำการคอมมิตหากคุณเข้าถึง DB โดยตรง (พูดจากพรอมต์ SQL) และตรวจสอบแถวที่แก้ไขคุณจะไม่เห็นการเปลี่ยนแปลง
นี่เหมือนกับการเปิด 2 เซสชันคำสั่ง SQL และการเปลี่ยนแปลงที่ทำใน 1 เซสชันจะไม่ปรากฏให้ผู้อื่นเห็นจนกว่าจะตกลง
ฉันรู้แค่ว่าเมื่อเราเรียกsession.flush()
คำสั่งของเราจะถูกดำเนินการในฐานข้อมูล แต่ไม่ได้กระทำ
สมมติว่าเราไม่ได้เรียกflush()
ใช้ method บนวัตถุเซสชันและถ้าเราเรียกใช้วิธีการกระทำมันจะทำงานภายในของการเรียกใช้คำสั่งบนฐานข้อมูลจากนั้นจึงทำการคอมมิต
commit=flush+commit
(ในกรณีที่ใช้งานได้)
ดังนั้นฉันจึงสรุปได้ว่าเมื่อเราเรียก method flush () บนวัตถุ Session มันจะไม่ได้รับการกระทำ แต่กระทบกับฐานข้อมูลและดำเนินการค้นหาและได้รับการย้อนกลับด้วย
ในการคอมมิตเราใช้คอมมิต () กับอ็อบเจกต์ธุรกรรม
การล้างเซสชันจะทำให้ข้อมูลที่อยู่ในเซสชันซิงโครไนซ์กับข้อมูลที่อยู่ในฐานข้อมูล
เพิ่มเติมบนเว็บไซต์ Hibernate:
flush()
จะเป็นประโยชน์เพราะมีอย่างค้ำประกันเกี่ยวกับเมื่อการประชุมดำเนินการ JDBC โทรเพียงเพื่อที่พวกเขาจะดำเนินการไม่ - flush()
ยกเว้นคุณใช้
คุณอาจใช้flush
เพื่อบังคับให้มีการรับรู้และตรวจพบข้อ จำกัด ในการตรวจสอบความถูกต้องในสถานที่ที่ทราบแทนที่จะเป็นเมื่อมีการทำธุรกรรม อาจเป็นไปได้ว่าcommit
ถูกเรียกโดยปริยายจากตรรกะของกรอบงานบางอย่างผ่านตรรกะที่เปิดเผยคอนเทนเนอร์หรือโดยเทมเพลต ในกรณีนี้ข้อยกเว้นใด ๆ ที่โยนไปอาจจับและจัดการได้ยาก (รหัสอาจสูงเกินไป)
ตัวอย่างเช่นหากคุณsave()
สร้างออบเจ็กต์ EmailAddress ใหม่ซึ่งมีข้อ จำกัด เฉพาะในที่อยู่คุณจะไม่ได้รับข้อผิดพลาดจนกว่าคุณจะยอมรับ
การเรียกflush()
บังคับให้แทรกแถวโดยจะโยน Exception หากมีการซ้ำกัน
อย่างไรก็ตามคุณจะต้องย้อนกลับเซสชันหลังจากข้อยกเว้น
ฉันต้องการเพียงแค่รวบรวมคำตอบทั้งหมดที่ให้ไว้ข้างต้นและเกี่ยวข้องกับวิธีการ Flush () กับ Session.save () เพื่อให้ความสำคัญมากขึ้น
Hibernate save () สามารถใช้เพื่อบันทึกเอนทิตีลงในฐานข้อมูล เราสามารถเรียกใช้วิธีนี้นอกธุรกรรมนั่นคือเหตุผลที่ฉันไม่ชอบวิธีนี้ในการบันทึกข้อมูล หากเราใช้สิ่งนี้โดยไม่มีธุรกรรมและเรามีการเรียงซ้อนระหว่างเอนทิตีระบบจะบันทึกเฉพาะเอนทิตีหลักเท่านั้นเว้นแต่เราจะล้างเซสชัน
flush (): บังคับให้เซสชันล้าง ใช้เพื่อซิงโครไนซ์ข้อมูลเซสชันกับฐานข้อมูล
เมื่อคุณเรียกใช้ session.flush () คำสั่งจะถูกดำเนินการในฐานข้อมูล แต่จะไม่ถูกคอมมิต ถ้าคุณไม่เรียก session.flush () และถ้าคุณเรียก session.commit () เมธอด Commit () ภายในจะรันคำสั่งและคอมมิต
ดังนั้นกระทำ () = ล้าง + กระทำ ดังนั้น session.flush () เพียงแค่รันคำสั่งในฐานข้อมูล (แต่ไม่คอมมิต) และคำสั่งจะไม่อยู่ในหน่วยความจำอีกต่อไป เพียงแค่บังคับให้เซสชันล้าง
ประเด็นสำคัญบางประการ:
เราควรหลีกเลี่ยงการบันทึกนอกขอบเขตธุรกรรมมิฉะนั้นเอนทิตีที่แมปไว้จะไม่ถูกบันทึกทำให้ข้อมูลไม่สอดคล้องกัน เป็นเรื่องปกติมากที่จะลืมล้างเซสชันเนื่องจากไม่มีข้อยกเว้นหรือคำเตือนใด ๆ โดยค่าเริ่มต้น Hibernate จะล้างการเปลี่ยนแปลงโดยอัตโนมัติสำหรับคุณ: ก่อนที่จะดำเนินการค้นหาบางอย่างเมื่อมีการทำธุรกรรมการอนุญาตให้ล้างเซสชันอย่างชัดเจนให้การควบคุมที่ละเอียดกว่าซึ่งอาจจำเป็นในบางสถานการณ์ (เพื่อรับ ID ที่กำหนดเพื่อควบคุมขนาดของเซสชัน )
flush()
วิธีการทำให้เกิด Hibernate เพื่อล้างเซสชั่น คุณสามารถกำหนดค่าไฮเบอร์เนตเพื่อใช้โหมดล้างสำหรับเซสชันได้โดยใช้setFlushMode()
วิธีการ หากต้องการรับโหมดล้างสำหรับเซสชันปัจจุบันคุณสามารถใช้getFlushMode()
วิธีการ หากต้องการตรวจสอบว่าเซสชันสกปรกหรือไม่คุณสามารถใช้isDirty()
วิธีการ โดยค่าเริ่มต้นไฮเบอร์เนตจะจัดการล้างเซสชัน
ตามที่ระบุไว้ในเอกสาร:
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html
ฟลัชชิง
ฟลัชชิงเป็นกระบวนการซิงโครไนซ์สถานะของบริบทการคงอยู่กับฐานข้อมูลพื้นฐาน
EntityManager
และ HibernateSession
เปิดเผยกำหนดวิธีการผ่านที่นักพัฒนาแอพลิเคชันสามารถเปลี่ยนรัฐถาวรของกิจการบริบทการคงอยู่ทำหน้าที่เป็นแคชการเขียนธุรกรรมโดยจัดคิวการเปลี่ยนแปลงสถานะเอนทิตีใด ๆ เช่นเดียวกับแคชการเขียนเบื้องหลังการเปลี่ยนแปลงจะถูกนำไปใช้ครั้งแรกในหน่วยความจำและซิงโครไนซ์กับฐานข้อมูลในช่วงเวลาล้าง การดำเนินการจะใช้เวลาล้างการเปลี่ยนแปลงทุกรัฐนิติบุคคลและแปลไปยัง
INSERT
,UPDATE
หรือDELETE
คำสั่งกลยุทธ์การล้างจะกำหนดโดยโหมดฟลัชโหมดของเซสชันไฮเบอร์เนตที่ทำงานอยู่ในปัจจุบัน แม้ว่า JPA จะกำหนดกลยุทธ์การล้างเพียงสองแบบ (
AUTO
และCOMMIT
) แต่ Hibernate มีประเภทการล้างที่กว้างกว่ามาก:
ALWAYS
: ล้างเซสชันก่อนการสืบค้นทุกครั้งAUTO
: นี่เป็นโหมดเริ่มต้นและจะล้างเซสชันหากจำเป็นเท่านั้นCOMMIT
: เซสชันพยายามชะลอการล้างจนกว่าจะมีการทำธุรกรรมปัจจุบันแม้ว่ามันอาจจะล้างก่อนเวลาอันควรด้วยก็ตามMANUAL
: การล้างเซสชันถูกมอบหมายให้กับแอปพลิเคชันซึ่งต้องเรียกSession.flush()
อย่างชัดเจนเพื่อใช้การเปลี่ยนแปลงบริบทการคงอยู่โดยค่าเริ่มต้นไฮเบอร์เนตจะใช้
AUTO
โหมดฟลัชซึ่งทำให้เกิดการล้างในสถานการณ์ต่อไปนี้:
- ก่อนที่จะทำธุรกรรม
- ก่อนที่จะดำเนินการแบบสอบถาม JPQL / HQL ที่ทับซ้อนกับการดำเนินการของเอนทิตีที่อยู่ในคิว
- ก่อนที่จะเรียกใช้แบบสอบถาม SQL ดั้งเดิมใด ๆ ที่ไม่มีการซิงโครไนซ์ที่ลงทะเบียน
โทรศัพท์EntityManager#flush
จะมีผลข้างเคียง ใช้อย่างสะดวกสำหรับประเภทเอนทิตีที่มีค่า ID ที่สร้างขึ้น (ค่าลำดับ): ID ดังกล่าวจะใช้ได้เฉพาะเมื่อซิงโครไนซ์กับเลเยอร์การคงอยู่ หากจำเป็นต้องใช้รหัสนี้ก่อนที่ธุรกรรมปัจจุบันจะสิ้นสุดลง (เพื่อวัตถุประสงค์ในการบันทึกเป็นต้น) จำเป็นต้องล้างเซสชัน
ด้วยวิธีนี้คุณทำให้เกิดกระบวนการล้าง กระบวนการนี้ซิงโครไนซ์สถานะของฐานข้อมูลของคุณกับสถานะของเซสชันของคุณโดยการตรวจจับการเปลี่ยนแปลงสถานะและเรียกใช้คำสั่ง SQL ที่เกี่ยวข้อง