ทำไมคุณถึงต้องการแคชแบบสอบถาม

ลองเขียนตัวอย่างใหม่โดยรับพนักงานใน HQL:

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

ผลลัพธ์ของแบบสอบถามดังกล่าวไม่ได้ถูกจัดเก็บโดยแคชระดับที่หนึ่งหรือสอง

นี่คือจุดที่ สามารถใช้ แคชแบบสอบถามได้ นอกจากนี้ยังปิดใช้งานตามค่าเริ่มต้น หากต้องการเปิดใช้งาน ให้เพิ่มบรรทัดต่อไปนี้ในไฟล์คอนฟิกูเรชัน:

<property name="hibernate.cache.use_query_cache" value="true"/>

แต่นี่เป็นเพียงครึ่งเดียวของการแก้ปัญหา เราได้เปิดใช้งานแคชของแบบสอบถาม แต่เราต้องระบุผลลัพธ์ของแบบสอบถามที่เราต้องการแคชด้วย สิ่งนี้จะต้องเขียนในแบบสอบถาม:

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

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

การล้างแคช

ภารกิจสำคัญประการหนึ่งเมื่อทำงานกับแคชคือต้องแน่ใจว่าอ็อบเจ็กต์ที่แคชเปลี่ยนแปลงและลบออกจากแคช (หรืออัปเดตวัตถุเหล่านั้น) ไฮเบอร์เนตทำได้ดีมาก บางครั้งดูเหมือนว่าเขาได้รับคำแนะนำจากกฎ "ล้างแคชในสถานการณ์ที่เข้าใจยาก"

สมมติว่าคุณต้องการอัปเดตข้อมูลผู้ใช้ผ่าน HQL:

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

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

แต่ NativeQuery นั้นน่าสนใจยิ่งกว่า:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

มีการเรียกใช้แบบสอบถาม SQL ดั้งเดิมไปยังฐานข้อมูลแล้ว ซึ่งหมายความว่ามีบางอย่างเปลี่ยนแปลงในฐานข้อมูล - คำขอถูกเรียกใน เมธอด executeUpdate( ) ดังนั้น ในกรณีนี้ ไฮเบอร์เนตจะเล่นอย่างปลอดภัยและลบออบเจกต์ทั้งหมดทุกประเภทออก จากแคช

คุณชอบสิ่งนั้นอย่างไร? คุณเรียกคำขอที่ไม่เป็นอันตราย และไฮเบอร์เนตตอบสนองจะลบข้อมูลทั้งหมดออกจากแคช! แน่นอนว่ามันดีกว่าที่เขาเก็บวัตถุที่แตกต่างจากฐาน แต่ก็นั่นแหละ!

ดังนั้นผู้สร้าง Hibernate จึงหาวิธีช่วย Hibernate ในกรณีนี้ได้อย่างรวดเร็ว คุณสามารถบอกได้ว่าจะลบเอนทิตีประเภทใดออกจากแคช:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
หมายเหตุ . เคียวรีแบบเลือกเนที ฟ ไม่ล้างแคชเฉพาะการแทรก อัพเดต ลบ การเรียกใช้โพรซีเดอร์ ฯลฯ

การล้างแคชด้วยตนเอง

ด้วยเหตุผลบางประการ คุณอาจต้องการลบวัตถุออกจากแคชด้วยตัวคุณเอง สามารถทำได้หลายวิธี

หมายเหตุ _ อ็อบเจกต์ในแคชถูกจัดเก็บไว้ในกลุ่มที่เรียกว่าภูมิภาค ตามค่าเริ่มต้น ชื่อภูมิภาคจะเหมือนกับชื่อคลาส ดังนั้น หากคุณมีอ็อบเจ็กต์ประเภทcom.codegym.Employeeอ็อบเจ็กต์ทั้งหมดจะถูกจัดเก็บไว้ในกลุ่ม (ภูมิภาค) ด้วยชื่อ " com.codegym.employee "

หากคุณต้องการเข้าถึงแคชและทำบางอย่างกับแคช คุณสามารถทำได้โดยใช้วัตถุ SessionFactory และเมธอด getCache () :

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

หากคุณต้องการลบข้อมูลจากทุกกลุ่ม (ภูมิภาค) คุณต้องเรียกใช้แบบสอบถามต่อไปนี้:

session.getSessionFactory().getCache().evictAllRegions();

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

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

คุณยังสามารถตรวจสอบว่ามีวัตถุใดอยู่ในแคชหรือไม่:

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);