البحث الرئيسي في هذه المقالة هو انتشار معاملات الربيع ومبادئ تنفيذها ، والتي يتم تقديمها على النحو التالي.
يعد Spring حاليًا معيارًا فعليًا لتطوير Java ، وذلك بفضل راحته ووظائفه الكاملة وسهلة الاستخدام. أثناء عملية التطوير ، يعد تشغيل DB عملية شائعة جدًا ، وعندما يتعلق الأمر بـ DB ، فإنها تتضمن معاملات. أثناء عملية التطوير العادية للمعاملات ، حتى لو لم تلاحظ ذلك ، فلن تكون هناك آثار جانبية على التنفيذ الطبيعي للبرنامج. ومع ذلك ، إذا حدث استثناء ولم يتم التعامل مع المعاملة بشكل صحيح ، فقد تحدث نتائج غير متوقعة. قام Spring بتغليف عمليات مختلفة من حيث المعاملات ، وخاصة ظهور المعاملات التعريفية ، مما يجعل التطوير أكثر راحة. يقوم Spring بتوسيع المعاملات ويدعم تعريف سمات الانتشار المتعددة ، وهو أيضًا محور هذه المقالة.
ليس بالمعنى الدقيق للكلمة ، فإن المعاملة هي اختصار عمليات متعددة. هذه العمليات إما تسري مفعولها أو أن أيا منها يسري (أي ما يعادل عدم تنفيذها). يتم تبسيط عملية التشغيل العامة على النحو التالي:
حاول {connection conn = getConnection () ؛ // تنفيذ بعض عمليات قاعدة البيانات} catch (استثناء e) {conn.rollback () ؛} أخيرًا {conn.close () ؛}يمكن رؤية بعض المشكلات من الكود أعلاه:
يوفر Spring معاملات تعريفية ، لذلك لا يتعين علينا الانتباه إلى التنفيذ المحدد للطبقة الأساسية ، ويمنع العديد من تفاصيل التنفيذ المختلفة للطبقة الأساسية. من أجل دعم التحكم الدقيق في المعاملات من قبل شركات معقدة متعددة ، يوفر Spring سمات الانتشار للمعاملات ، بالإضافة إلى المعاملات التعريفية ، أصبحت أداة معاملة رئيسية.
في فئة TransactionDefinition ، يوفر Spring 6 خصائص انتشار ، والتي يتم شرحها بأمثلة بسيطة.
تذكير دافئ: يشير ما يلي الانضمام إلى المعاملة الحالية إلى استخدام نفس الاتصال في الأسفل ، ولكن يمكن إعادة إنشاء كائن حالة المعاملة ولا يؤثر عليه. ذكرت المقالة أن هناك معاملة واحدة فقط في الوقت الحاضر ، مما يعني أنه يتم مشاركة الاتصال الأساسي ، ولا يهتم بعدد كائنات حالة المعاملة (المعاملات).
الوصف: في حالة وجود معاملة بالفعل ، انضم إلى المعاملة. إذا لم تكن هناك معاملة ، قم بإنشاء معاملة. هذه هي قيمة سمة الانتشار الافتراضية.
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
transactionalpublic void service () {servicea () ؛ ServiceB () ؛}@TransactionAlservicea () ؛@TransactionAlserviceb () ؛Servicea و ServiceB كلا الإعلان عن المعاملات. بشكل افتراضي ، الانتشار = spection_required. أثناء عملية مكالمات الخدمة بأكملها ، هناك معاملة مشتركة واحدة فقط. عند حدوث أي استثناء ، سيتم التراجع عن جميع العمليات.
الوصف: في حالة وجود معاملة بالفعل ، انضم إلى المعاملة ، وإلا يتم إنشاء ما يسمى بمعاملة فارغة (يمكن اعتبارها لا تنفذ معاملة).
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
خدمة void العامة () {servicea () ؛ رمي new RunTimeException () ؛}@المعاملات (الانتشار = الانتشار. دعم) servicea () ؛لا توجد معاملة حاليًا عند تنفيذ Servicea ، لذلك لن يتسبب الاستثناء الذي تم طرحه في الخدمة في تراجع Servicea.
دعونا نلقي نظرة على مثال صغير آخر ، الرمز هو كما يلي:
service public void service () {servicea () ؛}@exactactional (spected = spection.supports) servicea () {do sql 1 1/0 ؛ هل SQL 2}نظرًا لأن Servicea ليس لديه معاملات عند التشغيل ، في هذا الوقت ، إذا كان مصدر البيانات الأساسي defaultautoCommit = صحيح ، فإن SQL1 فعال. إذا كان defaultautocommit = خطأ ، فإن SQL1 غير صالح. إذا كانت الخدمة تحتوي على علامة transactional ، فإن Servicea تشارك معاملات الخدمة (لم تعد تعتمد على defaultautocommit). في هذا الوقت ، يتم التراجع عن Servicea.
الوصف: يجب أن توجد معاملة حاليًا ، وإلا سيتم طرح استثناء.
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
خدمة void العامة () {serviceB () ؛ servicea () ؛} serviceB () {do sql} transactional (الانتشار = الانتشار.في هذه الحالة ، ستعمل تنفيذ الخدمة على استثناء. إذا كان defaultautocommit = صحيح ، فلن يتم التراجع عن الخدمة. إذا كان defaultautocommit = خطأ ، فإن تنفيذ الخدمة سيكون غير صالح.
ملاحظة: في حالة وجود معاملة حاليًا ، قم أولاً بتغليف المحتوى الحالي المتعلق بالمعاملة في كيان ، ثم إعادة إنشاء معاملة جديدة ، وقبل هذا الكيان كمعلمة ، واستخدمه لاستعادة المعاملات. بيان أكثر حدة هو تعليق المعاملة الحالية (لا توجد حاجة إلى معاملة) وإنشاء معاملة جديدة. في هذه الحالة ، لا يوجد أي تبعية بين المعاملتين ، ويمكن تراجع المعاملة الجديدة ، لكن المعاملة الخارجية تستمر في التنفيذ.
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
transactionalpublic void service () {serviceB () ؛ حاول {servicea () ؛ } catch (استثناء e) {}} serviceB () {do sql} transactional (spection = spection.requires_new) servicea () {do sql 1 1/0 ؛ هل SQL 2}عند استدعاء واجهة الخدمة ، نظرًا لأن Servicea يستخدم يتطلب _new ، فسيقوم بإنشاء معاملة جديدة. ومع ذلك ، لأن Servicea يلقي استثناء وقت التشغيل ، يتم التراجع عن Servicea. في طريقة الخدمة ، يتم اكتشاف الاستثناءات ، لذلك يتم تقديم الخدمة بشكل طبيعي. لاحظ أن المحاولة ... كود في الخدمة ضروري ، وإلا فإن الخدمة ستلقي استثناء ، مما يتسبب في تراجع الخدمة.
ملاحظة: في حالة وجود معاملة حاليًا ، قم بتعليق المعاملة الحالية ، ثم يتم تنفيذ الطريقة الجديدة في بيئة بدون معاملات وفي بيئة بدون معاملات زنبركية ، يعتمد التزام SQL تمامًا على قيمة خاصية DefaultaUtocommit.
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
transactionalpublic void service () {serviceB () ؛ servicea () ؛} serviceB () {do sql} transactional (spection = spection.not_supported) servicea () {do sql 1 1/0 ؛ هل SQL 2}عندما يتم استدعاء طريقة الخدمة ، يتم طرح استثناء عند تنفيذ رمز 1/0 في طريقة Servicea. نظرًا لأن Servicea في بيئة خالية من المعاملات ، فإن ما إذا كان SQL1 فعالًا يعتمد على قيمة defaultautocommit. عندما يكون defaultautocommit = صحيح ، يكون SQL1 فعالًا ، ولكن سيتم إعادة خدمة ServiceB لأن الخدمة ترمي استثناء.
الوصف: في حالة وجود معاملة حاليًا ، يتم طرح استثناء ، وإلا يتم تنفيذ الكود في بيئة بدون معاملة.
دعونا نرى مثالًا صغيرًا ، الرمز كما يلي:
خدمة void العامة () {serviceB () ؛ servicea () ؛} serviceB () {do sql} transactional (spection = servation.never) servicea () {do sql 1 1/0 ؛ هل SQL 2}بعد المثال أعلاه ، خدمة المكالمات ، إذا كانت DefaultaUtocommit = صواب ، فإن طريقة الخدمة و SQL1 في Servicea ستصبح سارية المفعول.
ملاحظة: إذا كانت المعاملة موجودة حاليًا ، فاستخدم تقنية SavePoint لحفظ حالة المعاملة الحالية ، ثم تشترك الطبقة الأساسية في الاتصال. عندما يحدث خطأ داخل المتداخلة ، فإنه سيعود إلى حالة SavePoint بنفسها. طالما أن الاستثناء يتم اكتشافه من الخارج ، يمكن أن يستمر في ارتكاب معاملات خارجية دون أن ينزعج من العمل المضمن. ومع ذلك ، إذا تم إلقاء استثناء من خلال المعاملة الخارجية ، فسيتم التراجع عن المعاملة الكبيرة بأكملها.
ملاحظة: يجب على مدير معاملات تكوين الربيع تحديد نشط NETTERTANTACTINGED = صحيح ، كما هو موضح أدناه:
<bean id = "datatransactionManager"> <property name = "dataSource" ref = "datadataSource" /> <property name = "netterTransActioned" value = "true" /> </bean>
انظر مثال صغير ، الرمز كما يلي:
transactionalpublic void service () {servicea () ؛ حاول {serviceB () ؛ } catch (استثناء e) {}} servicea () {do sql }transActional (spection.nested) serviceB () {do sql1 1/0 ؛ هل SQL2}ServiceB هي خدمة مضمنة ، ويتم إلقاء استثناء وقت التشغيل داخليًا ، لذلك يتم إعادة خدمة ServiceB. منذ أن اشتعلت الخدمة الاستثناء ، يمكن لـ Servicea إرسالها بشكل طبيعي.
دعونا نلقي نظرة على مثال آخر ، الرمز هو كما يلي:
transactionalpublic void service () {servicea () ؛ serviceB () ؛ 1/0 ؛}@Transactional (spection = spection.nested) servicea () {do sql} serviceb () {do sql}نظرًا لأن الخدمة تطرح استثناء ، سيتم إعادة طريقة الخدمة بأكملها. (هذا يختلف عن الانتشار_
توضح الأمثلة المذكورة أعلاه العديد من سمات الانتشار التي توفرها معاملات الربيع لتلبية مجموعة متنوعة من احتياجات العمل المختلفة ، والتي يمكن تحديدها من قبل العمل. بعد ذلك ، دعونا نلقي نظرة على أهم التبعيات الفنية في الربيع التي تنفذ سمات الانتشار هذه. يسرد هذا القسم spection_requires_new والانتشار.
استدعاء الرمز التالي:
transactionalpublic void service () {serviceB () ؛ حاول {servicea () ؛ } catch (استثناء e) {}}@Transactional (spection = spection.requires_new) servicea () {do sql 1 1/0 ؛ هل sql 2} serviceb () {do sql}التخطيطي التنفيذي كما يلي:
أ. قم بإنشاء كائن حالة المعاملة ، واحصل على اتصال جديد ، وإعادة ضبط AutoCommit ، وجلبه ، ومهلة وخصائص أخرى للاتصال
ب. ربط الاتصال بمتغير threadlocal
ج. في انتظار المعاملة الحالية ، تغلف كائن حالة المعاملة الحالي والاتصال والمعلومات الأخرى في كائن معلق ، يمكن استخدامه للاسترداد
د. قم بإنشاء كائن حالة معاملة جديد ، وقم بإعادة توصيل اتصال جديد ، وإعادة ضبط AutoCommit ، وجلبه ، ومهنية وخصائص أخرى للاتصال الجديد. في الوقت نفسه ، احفظ كائن المعلقات المعلق لاستعادة المعاملات ، وربط الاتصال الجديد بمتغير Threadlocal (عملية الكتابة فوق)
ه. استثناء استثناء ، وتراجع الاتصال في Threadlocal ، واستعادة معلمات الاتصال ، وأغلق الاتصال ، واستعادة المعلقات
و. أرسل الاتصال في متغير ThreadLocal (تسبب في إرسال الخدمة) ، واستعادة معلمات الاتصال ، وإغلاق الاتصال ، وإرجاع الاتصال إلى مصدر البيانات
وبالتالي فإن نتيجة تنفيذ البرنامج هي أن Servicea يتم التراجع عنها وأن يتم تقديم الخدمة بنجاح.
استدعاء الرمز التالي:
transactionalpublic void service () {servicea () ؛ حاول {serviceB () ؛ } catch (استثناء e) {}} servicea () {do sql }transActional (spection.nested) serviceB () {do sql1 1/0 ؛ هل SQL2}التخطيطي التنفيذي كما يلي:
أ. قم بإنشاء كائن حالة المعاملة ، واحصل على اتصال جديد ، وإعادة ضبط AutoCommit ، وجلبه ، ومهلة وخصائص أخرى للاتصال
ب. ربط الاتصال بمتغير threadlocal
ج. حدد استخدام كائن حالة المعاملة الحالي ، والحصول على كائن اتصال ThreadLocal ، وحفظ نقطة التوصيل للاتصال الحالي ، ويستخدم لاسترداد الاستثناء. في هذا الوقت ، فإن نقطة التوفير هي الحالة بعد تنفيذ الخدمة
د. استثناء استثناء واستخدم SavePoint في C لتراجع المعاملات ، أي تراجع الدولة إلى الدولة بعد تنفيذ Servicea. جميع عمليات إعدام أساليب الخدمة لا تسري ساري المفعول
ه. احصل على كائن الاتصال في ThreadLocal ، وإرسال المعاملات ، واستعادة خصائص الاتصال ، واتصال وثيق
استنادًا إلى مصدر البيانات الأساسي ، يستخدم Spring Threadlocal و SavePoint وغيرها من النقاط الفنية لتحقيق مجموعة متنوعة من سمات انتشار المعاملات ، مما يسهل تنفيذ مختلف الخدمات المعقدة. فقط من خلال فهم مبدأ سمات الانتشار ، يمكننا التحكم بشكل أفضل في معاملات الربيع. تعتمد معاملات التراجع الربيعي على التقاط الاستثناءات. بشكل افتراضي ، لن يتم التراجع عن المعاملات إلا إذا تم طرح RunTimeException. بالطبع ، يمكن تكوينه. لمزيد من المعلومات ، يمكنك التحقق من التعليق التوضيحي transactional.
تجلب لنا المعاملات التعريفية الربيع راحة كبيرة. من أجل الاستفادة الجيدة من هذا السلاح ، لا يزال من الضروري فهم المبادئ الأساسية. هذه المقالة هي مجرد غيض من الجبل الجليدي لمعاملات الربيع. يمكن للقراء استكشاف بعمق على هذا الأساس.
ما سبق هو كل محتوى هذه المقالة حول انتشار معاملات الربيع ومبادئ تنفيذها. آمل أن يكون ذلك مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!