สำหรับคำอธิบายอีกต่อไปคุณสามารถอ่านของฉันเปิด Session ในมุมมองต่อต้านรูปแบบบทความ มิฉะนั้นนี่คือสรุปสาเหตุที่คุณไม่ควรใช้ Open Session In View
Open Session In View ใช้วิธีการที่ไม่ดีในการดึงข้อมูล แทนที่จะปล่อยให้ชั้นธุรกิจตัดสินใจว่าจะดึงการเชื่อมโยงทั้งหมดที่ต้องการโดยเลเยอร์ View ได้อย่างไร แต่จะบังคับให้ Persistence Context ยังคงเปิดอยู่เพื่อให้เลเยอร์ View สามารถทริกเกอร์การเริ่มต้น Proxy ได้
OpenSessionInViewFilter
เรียกopenSession
วิธีการพื้นฐานและได้รับใหม่SessionFactory
Session
- ถูกผูกไว้กับ
Session
TransactionSynchronizationManager
- การ
OpenSessionInViewFilter
เรียกใช้doFilter
การjavax.servlet.FilterChain
อ้างอิงอ็อบเจ็กต์และคำร้องขอจะถูกประมวลผลเพิ่มเติม
DispatcherServlet
เรียกว่าและเส้นทางการร้องขอ HTTP PostController
เพื่อพื้นฐาน
PostController
เรียกPostService
ที่จะได้รับรายชื่อของPost
หน่วยงาน
PostService
เปิดรายการใหม่และHibernateTransactionManager
reuses เดียวกันที่ถูกเปิดออกโดยSession
OpenSessionInViewFilter
PostDAO
เรียกรายชื่อของPost
หน่วยงานโดยไม่ต้องเริ่มต้นการเชื่อมโยงใด ๆ ขี้เกียจ
PostService
กระทำธุรกรรมพื้นฐาน แต่Session
ไม่ได้ปิดเพราะมันถูกเปิดออกภายนอก
- การ
DispatcherServlet
เริ่มต้นการแสดงผล UI ซึ่งในทางกลับกันจะนำทางการเชื่อมโยงแบบ lazy และทริกเกอร์การเริ่มต้น
OpenSessionInViewFilter
สามารถปิดSession
และเชื่อมต่อฐานข้อมูลพื้นฐานจะถูกปล่อยออกเช่นกัน
เมื่อมองแวบแรกสิ่งนี้อาจดูเหมือนไม่ใช่เรื่องน่ากลัวที่ต้องทำ แต่เมื่อคุณดูจากมุมมองของฐานข้อมูลข้อบกพร่องต่างๆจะเริ่มชัดเจนขึ้น
ชั้นบริการเปิดและปิดธุรกรรมฐานข้อมูล แต่หลังจากนั้นไม่มีธุรกรรมที่ชัดเจนเกิดขึ้น ด้วยเหตุนี้ทุกคำสั่งเพิ่มเติมที่ออกจากเฟสการเรนเดอร์ UI จะถูกดำเนินการในโหมดการคอมมิตอัตโนมัติ การคอมมิตอัตโนมัติจะสร้างแรงกดดันให้กับเซิร์ฟเวอร์ฐานข้อมูลเนื่องจากแต่ละคำสั่งต้องล้างบันทึกธุรกรรมลงในดิสก์ดังนั้นจึงทำให้มีการรับส่งข้อมูล I / O จำนวนมากที่ฝั่งฐานข้อมูล การเพิ่มประสิทธิภาพอย่างหนึ่งคือการทำเครื่องหมายConnection
ว่าอ่านอย่างเดียวซึ่งจะช่วยให้เซิร์ฟเวอร์ฐานข้อมูลหลีกเลี่ยงการเขียนลงในบันทึกธุรกรรม
ไม่มีการแยกข้อกังวลอีกต่อไปเนื่องจากคำสั่งถูกสร้างขึ้นโดยชั้นบริการและโดยกระบวนการแสดงผล UI การเขียนการทดสอบการรวมที่ยืนยันจำนวนคำสั่งที่สร้างขึ้นจะต้องผ่านทุกเลเยอร์ (เว็บบริการ DAO) ในขณะที่มีการปรับใช้แอปพลิเคชันบนเว็บคอนเทนเนอร์ แม้ว่าจะใช้ฐานข้อมูลในหน่วยความจำ (เช่น HSQLDB) และเว็บเซิร์ฟเวอร์ที่มีน้ำหนักเบา (เช่น Jetty) การทดสอบการรวมเหล่านี้จะดำเนินการได้ช้ากว่าการแยกชั้นและการทดสอบการรวมส่วนหลังจะใช้ฐานข้อมูลในขณะที่ การทดสอบการรวมส่วนหน้ากำลังจำลองชั้นบริการโดยสิ้นเชิง
เลเยอร์ UI จำกัด เฉพาะการนำทางที่เชื่อมโยงซึ่งสามารถทำให้เกิดปัญหาการสืบค้น N + 1 ได้ในทางกลับกัน แม้ว่าไฮเบอร์เนตจะเสนอ@BatchSize
การดึงการเชื่อมโยงเป็นกลุ่มและFetchMode.SUBSELECT
เพื่อรับมือกับสถานการณ์นี้ แต่คำอธิบายประกอบจะส่งผลต่อแผนการดึงข้อมูลเริ่มต้นดังนั้นจึงนำไปใช้กับทุกกรณีการใช้งานทางธุรกิจ ด้วยเหตุนี้แบบสอบถามชั้นการเข้าถึงข้อมูลจึงเหมาะสมกว่ามากเนื่องจากสามารถปรับแต่งให้เหมาะกับข้อกำหนดการดึงข้อมูลกรณีการใช้งานปัจจุบัน
สุดท้าย แต่ไม่ท้ายสุดการเชื่อมต่อฐานข้อมูลอาจถูกระงับตลอดระยะการแสดงผล UI (ขึ้นอยู่กับโหมดการปล่อยการเชื่อมต่อของคุณ) ซึ่งจะเพิ่มเวลาเช่าการเชื่อมต่อและ จำกัด ปริมาณงานธุรกรรมโดยรวมเนื่องจากความแออัดในพูลการเชื่อมต่อฐานข้อมูล ยิ่งมีการเชื่อมต่อมากขึ้นคำขออื่น ๆ ที่พร้อมกันจะต้องรอรับการเชื่อมต่อจากพูลมากขึ้น
ดังนั้นไม่ว่าคุณจะถูกระงับการเชื่อมต่อไว้นานเกินไปหรือคุณได้รับ / ปล่อยการเชื่อมต่อหลายรายการสำหรับคำขอ HTTP เดียวดังนั้นจึงกดดันพูลการเชื่อมต่อที่อยู่เบื้องหลังและ จำกัด ความสามารถในการปรับขยาย
สปริงบูต
แต่น่าเสียดายที่เปิดเซสชันในวิวถูกเปิดใช้งานโดยเริ่มต้นในฤดูใบไม้ผลิ Boot
ดังนั้นตรวจสอบให้แน่ใจว่าในapplication.properties
ไฟล์กำหนดค่าคุณมีรายการต่อไปนี้:
spring.jpa.open-in-view=false
นี้จะปิดการใช้งาน OSIV เพื่อให้คุณสามารถจัดการกับLazyInitializationException
วิธีการที่เหมาะสม