กลยุทธ์การทำงานพร้อมกัน
หลังจากที่คุณเปิดใช้งานการแคชระดับที่สองใน Hibernate คุณต้องอธิบายให้ Hibernate ทราบว่าเราต้องการแคชวัตถุเอนทิตีใดและอย่างไร
ในการทำเช่น นี้Hibernate มีคำอธิบายประกอบพิเศษสำหรับคลาสเอนทิตี - @Cache ตัวอย่าง:
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
คำอธิบายประกอบนี้จำเป็นต้องเขียนสำหรับแต่ละเอนทิตีเอนทิตีที่เราต้องการใช้แคชระดับที่สอง ตัวอย่าง:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
private Set<Task> tasks;
}
ไฮเบอร์เนตมี 4 กลยุทธ์การเข้าถึงที่เป็นไปได้สำหรับเอนทิตีแคช หากเข้าถึงจากเธรดที่แตกต่างกัน:
- อ่านเท่านั้น
- อ่านเขียน
- อ่าน-เขียนแบบไม่เคร่งครัด
- ธุรกรรม
อ่านอย่างเดียว กลยุทธ์การทำงานพร้อมกันที่เหมาะสมกับข้อมูลที่ไม่เคยเปลี่ยนแปลง ไฮเบอร์เนตจะเก็บวัตถุเหล่านี้ไว้ในหน่วยความจำ ใช้สำหรับข้อมูลอ้างอิงเท่านั้น
ฐานข้อมูลเก็บข้อมูลจำนวนมากที่ไม่เคยเปลี่ยนแปลง ตัวอย่างเช่น ตารางจะเก็บรายการเหตุการณ์ที่เพิ่มเท่านั้นแต่ไม่เคยเปลี่ยนแปลงหรือลบออก หากคุณต้องการทำงานกับตารางนี้ผ่าน Hibernate กลยุทธ์การแคชแบบอ่านอย่างเดียวจะเหมาะกับคุณ
อ่าน-เขียน (อ่าน-เขียน). ใช้กลยุทธ์นี้สำหรับข้อมูลที่อ่านได้เป็นหลัก อย่างไรก็ตาม Hibernate จะติดตามความพยายามในการเปลี่ยนแปลงข้อมูลนี้ แม้ว่าคาดว่าจะเกิดขึ้นไม่บ่อยนัก
คุณต้องแคชวัตถุส่วนใหญ่ที่ไม่ค่อยเปลี่ยนแปลงและมักจะอ่าน / ร้องขอ หากคุณมีวัตถุดังกล่าว คุณต้องใช้กลยุทธ์การอ่าน-เขียนสำหรับวัตถุเหล่านั้น
ไม่เข้มงวดอ่าน-เขียน กลยุทธ์นี้ไม่รับประกันความสอดคล้องระหว่างแคชและฐานข้อมูล ใช้กลยุทธ์นี้หากข้อมูลแทบไม่เคยเปลี่ยนแปลงเลย และมีโอกาสเล็กน้อยที่ข้อมูลเก่าจะไม่ใช่ปัญหาร้ายแรง
ไม่เหมือนกับกลยุทธ์การอ่าน-เขียน กลยุทธ์นี้ถือว่าข้อมูลที่ไม่แน่นอนไม่ได้ล็อกไว้สำหรับการอ่าน ซึ่งอาจส่งผลให้วัตถุมีการเปลี่ยนแปลงในที่หนึ่ง ในขณะที่อีกที่หนึ่ง บางคนกำลังอ่านเวอร์ชันเก่าอยู่
ตัวอย่างเช่น ผู้ใช้เปลี่ยนความคิดเห็นของเขา แต่ผู้ใช้รายอื่นยังคงเห็นเวอร์ชันเก่าของเขาในบางครั้ง หากนี่ไม่ใช่ปัญหาสำหรับคุณ ให้ใช้กลยุทธ์การอ่าน-เขียนแบบไม่เข้มงวด
การทำธุรกรรม ใช้กลยุทธ์นี้สำหรับข้อมูลแบบอ่านอย่างเดียวเป็นหลัก ซึ่งเป็นสิ่งสำคัญในการป้องกันข้อมูลเก่าในการทำธุรกรรมพร้อมกันในโอกาสที่หายากของการอัปเดต
การจัดเก็บข้อมูลในแคช
รายละเอียดที่สำคัญอีกประการเกี่ยวกับแคชระดับที่สองที่คุณควรจำไว้ก็คือ Hibernate จะไม่เก็บอ็อบเจกต์ของคลาสของคุณเอง มันเก็บข้อมูลเป็นอาร์เรย์ของสตริง ตัวเลข ฯลฯ
และตัวระบุวัตถุทำหน้าที่เป็นตัวชี้ไปยังข้อมูลนี้ ตามแนวคิดแล้ว นี่คือสิ่งที่เหมือนกับ Map ซึ่งรหัสของวัตถุคือคีย์ และอาร์เรย์ข้อมูลคือค่า คุณสามารถจินตนาการได้ดังนี้:
1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }
ซึ่งสมเหตุสมผลมากเมื่อพิจารณาว่าแต่ละออบเจกต์ใช้หน่วยความจำเพิ่มเติมเท่าใด
นอกเหนือจากข้างต้น คุณควรจำไว้ว่าการขึ้นต่อกันของคลาสเอนทิตีของคุณจะไม่ถูกแคชไว้โดยค่าเริ่มต้น ตัวอย่างเช่น หากเราถือว่าคลาสด้านบนคือEmployeeเมื่อทำการดึงข้อมูล การรวบรวมงานจะถูกดึงมาจากฐานข้อมูลไม่ใช่จากแคชระดับที่สอง
หากคุณต้องการแคชการอ้างอิงด้วย คลาสควรมีลักษณะดังนี้:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Task> tasks;
}
และรายละเอียดสุดท้าย - การอ่านจากแคชระดับที่สองจะเกิดขึ้นก็ต่อเมื่อไม่พบวัตถุที่ต้องการในแคชระดับแรก
โหมดแคช
ไฮเบอร์เนตช่วยให้การจัดการแคชมีความยืดหยุ่นมาก คุณสามารถตั้งค่าโหมดแคชสำหรับแต่ละเซสชันหรือแม้กระทั่งสำหรับคำขอฐานข้อมูลแต่ละรายการ
มีห้าโหมดดังกล่าว:
- รับ
- ไม่สนใจ
- ปกติ
- ใส่
- รีเฟรช
ตารางด้านล่างอธิบายงานของพวกเขา:
โหมดแคช | คำอธิบาย |
---|---|
รับ | ข้อมูลถูกอ่านจากแคช แต่ไม่ได้เพิ่มเข้าไป |
ไม่สนใจ | เซสชันไม่โต้ตอบกับแคช |
ปกติ | ข้อมูลถูกอ่านจากแคชและเพิ่มเข้าไป |
ใส่ | ข้อมูลจะไม่ถูกดึงออกจากแคช แต่เพิ่มเข้าไป |
รีเฟรช | ข้อมูลจะไม่ถูกดึงออกจากแคช แต่เพิ่มเข้าไป ในโหมดนี้ จะใช้การตั้งค่า hibernate.cache.use_minimal_puts เพิ่มเติม |
ตัวอย่างของการตั้งค่าโหมดแคชสำหรับเซสชัน:
session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();
และตัวอย่างของการตั้งค่าโหมดสำหรับเซสชันและคำขอ:
session.setCacheMode(CacheMode.GET);
Query query = session.createQuery("from Employee where id = 4");
query.setCacheMode(CacheMode.IGNORE); // Ignore cache work for this request
Employee director = query.uniqueResult();