0Pricing
Java Academy · درس

المعاملات

التثبيت والتراجع

المعاملات درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

ما المعاملة؟

تجمع المعاملة عدة عمليات SQL في وحدة واحدة تُنفَّذ بالكامل أو لا تُنفَّذ إطلاقًا.

إما أن تنجح جميع العبارات وتصبح التغييرات دائمة (الالتزام)، أو يحدث خطأ فتُلغى جميعها (التراجع). وهذا يحافظ على اتساق قاعدة البيانات.

ACID في دقيقة واحدة

توفر المعاملات ضمانات ACID التالية:

  • الذرّية — الكل أو لا شيء.
  • الاتساق — تنقل قاعدة البيانات من حالة صالحة إلى حالة صالحة أخرى.
  • العزل — لا تُفسد المعاملات المتزامنة إحداها الأخرى.
  • الديمومة — بعد الالتزام، تبقى التغييرات حتى بعد حدوث عطل.

وضع الالتزام التلقائي

تعمل اتصالات JDBC افتراضيًا في وضع الالتزام التلقائي: كل عبارة هي معاملتها الخاصة، ويُلتزم بها فورًا.

هذا مناسب للعبارات المنفردة، لكنه لا يفيد عندما يجب أن تنجح عدة عمليات كتابة معًا. وللتحكم في المعاملات بأنفسكم، أوقفوا الالتزام التلقائي.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            System.out.println("Default auto-commit: " + conn.getAutoCommit());
            conn.setAutoCommit(false);
            System.out.println("Now manual: " + conn.getAutoCommit());
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

الالتزام والتراجع

عند إيقاف الالتزام التلقائي، تحددون أنتم الحدود:

  • يجعل conn.commit() جميع التغييرات المعلّقة دائمة.
  • يلغي conn.rollback() تلك التغييرات.

المثال الكلاسيكي هو تحويل الأموال: خصم المبلغ من حساب وإضافته إلى حساب آخر. يجب تنفيذ العمليتين معًا، أو عدم تنفيذ أيٍّ منهما.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        String debit = "UPDATE account SET balance = balance - ? WHERE id = ?";
        String credit = "UPDATE account SET balance = balance + ? WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            conn.setAutoCommit(false);
            try (PreparedStatement d = conn.prepareStatement(debit);
                 PreparedStatement c = conn.prepareStatement(credit)) {
                d.setInt(1, 100); d.setInt(2, 1); d.executeUpdate();
                c.setInt(1, 100); c.setInt(2, 2); c.executeUpdate();
                conn.commit();
                System.out.println("Transfer committed");
            } catch (SQLException ex) {
                conn.rollback();
                System.out.println("Rolled back: " + ex.getMessage());
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

نمط التراجع عند الفشل

البنية التي ينبغي حفظها:

  • أوقفوا الالتزام التلقائي.
  • نفّذوا العمل داخل try داخلي.
  • عند النجاح، استدعوا commit().
  • في catch، استدعوا rollback() ثم أعيدوا رمي الاستثناء أو سجّلوه.

من دون التراجع، قد يترك الفشل قاعدة البيانات محدَّثة جزئيًا.

محاكاة الذرّية

إليكم فكرة التنفيذ الكامل أو عدم التنفيذ إطلاقًا، ممثلةً بلغة Java عادية كي تعمل بشكل مستقل. نطبّق تحديثين على لقطة؛ وإذا فشل أيٌّ منهما، نستعيد اللقطة.

public class Main {
    public static void main(String[] args) {
        int[] balances = {500, 300};
        int[] backup = balances.clone();
        try {
            balances[0] -= 200;
            if (balances[0] < 0) throw new IllegalStateException("insufficient funds");
            balances[1] += 200;
            System.out.println("Commit: " + balances[0] + ", " + balances[1]);
        } catch (RuntimeException e) {
            balances = backup;
            System.out.println("Rollback: " + balances[0] + ", " + balances[1]);
        }
    }
}

نقاط الحفظ

نقطة الحفظ هي علامة داخل المعاملة. يمكنكم التراجع إليها دون إلغاء المعاملة بأكملها.

  • Savepoint sp = conn.setSavepoint()
  • يلغي conn.rollback(sp) العمل الذي أُنجز بعد تلك النقطة فقط.

وهي مفيدة للاستعادة الجزئية في المعاملات الطويلة.

مستويات العزل

يتحكم العزل فيما تراه معاملة من عمل معاملة أخرى غير الملتزم به. وتحدد JDBC المستويات عبر conn.setTransactionIsolation(...):

  • TRANSACTION_READ_COMMITTED — الإعداد الافتراضي الشائع.
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE — الأقوى والأبطأ.

تمنع مستويات العزل الأعلى الظواهر غير الطبيعية، لكنها تقلل التزامن.

ظواهر القراءة غير الطبيعية

قد تسمح مستويات العزل المنخفضة بما يلي:

  • القراءة القذرة — رؤية تغيير غير ملتزم به أجرته معاملة أخرى.
  • القراءة غير القابلة للتكرار — تغيّر صف بين عمليتي قراءة.
  • القراءة الوهمية — ظهور صفوف جديدة تطابق استعلامًا سابقًا.

اختاروا أدنى مستوى يمنع الظواهر التي لا يستطيع منطقكم تحمّلها.

استعادة الالتزام التلقائي

إذا استعَرتم الاتصال من تجمّع، فأعيدوا حالته الأصلية قبل إرجاعه.

بعد معاملة يدوية، عيّنوا conn.setAutoCommit(true) مجددًا، أو أعيدوه إلى القيمة التي سجّلتموها عند الاستعارة، حتى لا يفاجأ المستخدم التالي بإعداداتكم.

أبقوا المعاملات قصيرة

تحتفظ المعاملة بالأقفال حتى تُجري الالتزام أو التراجع. وتحجب المعاملات الطويلة الأعمال الأخرى وتزيد خطر التعارض التام.

  • لا تُجروا استدعاءات شبكة بطيئة أو تطلبوا إدخالًا من المستخدم داخل معاملة مفتوحة.
  • اجمعوا بياناتكم أولًا، ثم افتحوا المعاملة واكتبوا والتزموا بسرعة.

تتوسع المعاملات القصيرة والمركّزة بكفاءة أكبر بكثير.

تحقق سريع

ما تأثير استدعاء connection.rollback()؟

مراجعة

تمنحكم المعاملات أمان التنفيذ الكامل أو عدم التنفيذ إطلاقًا:

  • أوقفوا الالتزام التلقائي باستخدام setAutoCommit(false).
  • استدعوا commit() عند النجاح وrollback() عند الفشل.
  • استخدموا نقاط الحفظ للتراجع الجزئي.
  • اضبطوا مستويات العزل لتحقيق التوازن بين الصحة والتزامن.
  • أعيدوا الالتزام التلقائي قبل إرجاع اتصال إلى التجمّع.

الأسئلة الشائعة

هل درس «المعاملات» مجاني؟

نعم — نص درس «المعاملات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «المعاملات»؟

التثبيت والتراجع تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «المعاملات»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات JDBC
  2. PreparedStatement
  3. المعاملات
  4. تجميع الاتصالات باستخدام HikariCP
← العودة إلى Java Academy