تخزين التخزين – الذاكرة المؤقتة من المستوى الأول

مرحبًا بك في تعليمة مثال الذاكرة المؤقتة لـ Hibernate – مستوى الذاكرة المؤقتة الأول. في الآونة الأخيرة، قمنا بالنظر في هندسة Hibernate، تعيين Hibernate وكيفية استخدام HQL لإطلاق استعلامات SQL بطريقة موجهة نحو الكائنات. اليوم سننظر في واحدة من الجوانب الهامة لـ Hibernate – ذاكرة التخزين المؤقت لـ Hibernate.

ذاكرة التخزين المؤقت لـ Hibernate

يمكن أن تكون ذاكرة التخزين المؤقت لـ Hibernate مفيدة للغاية في تحسين أداء التطبيق بسرعة إذا استُخدمت بشكل صحيح. الفكرة الأساسية وراء الذاكرة المؤقتة هي تقليل عدد استعلامات قواعد البيانات، وبالتالي تقليل وقت الاستجابة للتطبيق. يأتي Hibernate مع أنواع مختلفة من الذاكرة المؤقتة:

  1. المخزن المؤقت من المستوى الأول: المخزن المؤقت من المستوى الأول في Hibernate مرتبط بكائن الجلسة. يتم تمكين المخزن المؤقت من المستوى الأول في Hibernate تلقائيًا ولا يوجد طريقة لتعطيله. ومع ذلك، يوفر Hibernate طرقًا يمكننا من خلالها حذف الكائنات المحددة من التخزين المؤقت أو مسح التخزين المؤقت تمامًا. لن يكون أي كائن مخزن في جلسة مرئيًا لجلسات أخرى وعند إغلاق الجلسة، ستفقد جميع الكائنات المخزنة أيضًا.
  2. المخزن المؤقت من المستوى الثاني: المخزن المؤقت من المستوى الثاني في Hibernate معطل افتراضيًا ولكن يمكننا تمكينه من خلال التكوين. حاليًا، توفر EHCache و Infinispan تنفيذًا للمخزن المؤقت من المستوى الثاني في Hibernate ويمكننا استخدامهما. سننظر إلى هذا في البرنامج التعليمي التالي لتخزين Hibernate.
  3. مخزن الاستعلام: يمكن أيضًا لـ Hibernate تخزين نتيجة مجموعة النتائج لاستعلام. لا يقوم مخزن الاستعلام في Hibernate بتخزين حالة الكيانات الفعلية في التخزين المؤقت؛ بل يقوم فقط بتخزين قيم معرف ونتائج نوع القيمة. لذا يجب دائمًا استخدامه بالتزامن مع التخزين المؤقت من المستوى الثاني.

تخزين Hibernate – مثال على المخزن المؤقت من المستوى الأول

لبرنامج مثال تخزينة مستوى أول في Hibernate الخاص بي، أستخدم نفس التكوين كما في مثال HQL، يمكنك التحقق من ذلك وتكوين الجداول وملءها بالبيانات الوهمية. دعنا نلقي نظرة أولاً على البرنامج وإخراجه ثم سنتعرض لبعض النقاط المهمة المتعلقة بـ Hibernate First Level Cache. HibernateCacheExample.java

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateCacheExample {

	public static void main(String[] args) throws InterruptedException {
		
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		//احصل على موظف بمعرف = 1
		Employee emp = (Employee) session.load(Employee.class, new Long(1));
		printData(emp,1);
		
		//انتظر بعض الوقت لتغيير البيانات في الخلفية
		Thread.sleep(10000);
		
		//استرجع نفس البيانات مرة أخرى ، تحقق من السجلات أنه لم يتم تشغيل أي استعلام
		Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp1,2);
		
		//إنشاء جلسة جديدة
		Session newSession = sessionFactory.openSession();
		//احصل على موظف بمعرف = 1, notice the logs for query
		Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
		printData(emp2,3);
		
		//بداية: مثال على إزالة كائن محدد من ذاكرة التخزين المؤقت في مستوى أول في Hibernate
		//احصل على موظف بمعرف = 2 ، لأول مرة لذلك يتم تسجيل الاستعلام في السجلات
		Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp3,4);
		
		//قم بإزالة كائن الموظف بمعرف = 1 من الذاكرة المؤقتة في المستوى الأول
		session.evict(emp);
		System.out.println("Session Contains Employee with id=1?"+session.contains(emp));

		//نظرًا لإزالة الكائن من ذاكرة التخزين المؤقت في المستوى الأول ، سترى الاستعلام في السجلات
		Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp4,5);
		
		//هذا الكائن لا يزال موجودًا ، لذلك لن ترى الاستعلام في السجلات
		Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp5,6);
		//نهاية: مثال على مسح كل شيء من ذاكرة التخزين المؤقت في المستوى الأول
		
		//بداية: مثال على إزالة كل شيء من ذاكرة التخزين المؤقت في المستوى الأول
		session.clear();
		Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp6,7);
		Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp7,8);
		
		System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
		
		tx.commit();
		sessionFactory.close();
	}

	private static void printData(Employee emp, int count) {
		System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
	}

}

عند تشغيل المثال أعلاه ، يحتوي الإخراج على الكثير من المعلومات المتعلقة بـ Hibernate. ولكننا مهتمون بشكل رئيسي بإخراج الشفرة الخاص بنا والاستعلامات التي يطلقها Hibernate لتحميل البيانات. تبدو مقتطف الإخراج على النحو التالي.

Hibernate Configuration loaded
Hibernate serviceRegistry created
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
1:: Name=Pankaj, Zipcode=95129
2:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
3:: Name=PankajK, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
4:: Name=David, Zipcode=95051
Session Contains Employee with id=1?false
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
5:: Name=Pankaj, Zipcode=95129
6:: Name=David, Zipcode=95051
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
7:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
8:: Name=David, Zipcode=95051
Session Contains Employee with id=2?true

نقاط مهمة حول الذاكرة المؤقتة من المستوى الأول في هايبرنيت

النقاط الهامة حول الذاكرة المؤقتة من المستوى الأول في Hibernate التي يمكن استنتاجها من البرنامج أعلاه هي:

  1. الذاكرة المؤقتة من المستوى الأول في Hibernate مُمكّنة افتراضيًا، ولا تحتاج إلى أي تكوينات لذلك.
  2. الذاكرة المؤقتة من المستوى الأول في Hibernate محددة للجلسة، ولهذا السبب عند الحصول على نفس البيانات في نفس الجلسة، لا يتم إطلاق استعلام، بينما في جلسة أخرى يتم إطلاق استعلام لتحميل البيانات.
  3. قد تحتوي الذاكرة المؤقتة من المستوى الأول في Hibernate على قيم قديمة، كما يمكن رؤية أنني قمت بتعليق البرنامج لمدة 10 ثوانٍ وفي تلك الفترة قمت بتحديث القيمة (الاسم من Pankaj إلى PankajK) في قاعدة البيانات ولكن لم يتم تعكيرها في نفس الجلسة. ولكن في جلسة أخرى، حصلنا على القيمة المحدثة.
  4. يمكننا استخدام طريقة evict() في الجلسة لإزالة كائن واحد من ذاكرة المستوى الأول في Hibernate.
  5. يمكننا استخدام طريقة clear() في الجلسة لمسح الذاكرة المؤقتة أي حذف جميع الكائنات من الذاكرة المؤقتة.
  6. يمكننا استخدام طريقة contains() في الجلسة للتحقق مما إذا كان كائن موجودًا في ذاكرة المستوى الأول في Hibernate أم لا، وإذا تم العثور على الكائن في الذاكرة المؤقتة، يعيد القيمة صحيحة وإلا يعيد القيمة خاطئة.
  7. نظرًا لأن Hibernate يخزن جميع الكائنات في ذاكرة المستوى الأول في الجلسة، فإنه أثناء تشغيل استعلامات السائل الكثيفة أو التحديثات الجماعية، يتعين مسح الذاكرة المؤقتة في فترات معينة لتجنب مشاكل الذاكرة.

هذا كل شيء بالنسبة لتخزين Hibernate ومثال على الذاكرة المؤقتة من المستوى الأول، في المقالات المستقبلية سنتطرق إلى تنفيذ ذاكرة مؤقتة من المستوى الثاني لـ Hibernate – EHCache .

Source:
https://www.digitalocean.com/community/tutorials/hibernate-caching-first-level-cache