กลยุทธ์การทำงานพร้อมกัน

หลังจากที่คุณเปิดใช้งานการแคชระดับที่สองใน 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();