-
Notifications
You must be signed in to change notification settings - Fork 0
Customize_ar
إن أردت إنشاء أوامرك الخاصّة فعليك فهم طبيعة عمل الخادم وكيف ينفّذ الأوامر, وذلك يعتمد بالضرورة على رؤيتك لكيفيّة عمل قاعدة البيانات, فهي ليست مجموعة أوامر جاهزةٍ يتبنّاها الخادم, بل هي بيئة لتنفيذ الأوامر مهما كان مصدرها وطبيعة عملها, مما يسمح لأيّ شخصٍ بكتابة أوامره الّتي ستخدمه في أيّ مجالٍ يريده (تجميع البيانات الضّخمة, كتابة السّجلات, مشاركة البيانات, إلخ), ويعتمد الخادم بالأساس على النافذتين ListInputStream و ListOutputStream, ووظيفة هاتين النافذتين تشبه إلى حدٍّ بعيدٍ وظيفة الأمرين Bind و Select, ويقوم الخادم بتمرير الimplementation لكليهما في حالة تنفيذ أمرٍ تنفيذيٍّ إلى الدّالّة execute و ListInputStream إلى الدّالّة query في حالة تنفيذ استعلام, مما يعطي الأمر إمكانيّة قراءة وكتابة البيانات من وإلى قاعدة البيانات, فالنافذة ListOutputStream لها دالّة لكتابة القوائم وهي write والّتي تستقبل القائمة واسم الربط والصّفّ على التّرتيب, وعند تنفيذها ستقوم بمسح جميع كائنات الصّفّ الممرر المرتبطة باسم الرّبط ثم تكتب الكائنات الجديدة, أمّا ListInputStream فيسمح بالقراءة من خلال الدالّة read والّتي تستقبل اسم الرّبط والصّفّ الذي ستقرأ كائناته جميعها المرتبطة باسم الربط. إنّ ما يحدث في حال استقبال الخادم أكثر من أمرٍ سواء أكان تنفيذيًّا أم استعلامًا يستوجب الاهتمام في حال أردت بناء أوامرك الخاصّة, فعندما يستقبل الخادم أكثر من طلب سيبدأ بتنفيذها مباشرةً, فإن كان هناك أمران يقومان بالقراءة من نفس الصفّ المرتبط باسم ربطٍ معيّنٍ (وهو أصغر وحدة في قاعدة البيانات) سيسمح لهما بالقراءة, أمّا في حالة تنفيذ أمرٍ تنفيذيٍّ سينتظر الجميع حتى ينتهي ذلك الأمر, وذلك يعود لكون الأمر التّنفيذيّ يستطيع القيام بالعديد من الأوامر والّتي تتطلب ثبات قاعدة البيانات أثناء تنفيذها, وذلك يتطلب منك ككاتب أوامر مراعاة سرعة تنفيذ الأمر التّنفيذيّ. نأتي الآن للمثال الذي سيوضح لك كل ما سبق:
import org.sofof.command.Executable;
import org.sofof.ListInputStream;
import org.sofof.ListOutputStream;
public class Format implements Executable {
private String bind;
private Class[] classes;
public Example(String bind, Class... classes) {
this.bind = bind;
this.classes = classes;
}
@Override
public int execute(ListInputStream in, ListOutputStream out) throws SofofException {
int affected = 0;
for (Class clazz : classes) {
affected +=in.read(bind, clazz).size();
out.write(new LinkedList(), bind, clazz);
}
return affected;
}
}هذا مثالٌ بسيطٌ لأمرٍ تنفيذيٍّ يقوم بمسح جميع الكائنات من عدّة صفوفٍ مرتبطةٍ بنفس اسم الربط دفعةً واحدةً, ويجب عند انتهاء الأمر إعادة عدد الكائنات المُتأثّرة. أمّا بالنّسبة للاستعلام فسنقوم بكتابة استعلامٍ يعيد خرائط بأسماء الطّلاب ومعدّل علامات كلّ واحدٍ:
import org.sofof.command.Operation;
import example.Student;
import example.Marks;
import org.sofof.command.Query;
import org.sofof.command.Select;
import org.sofof.command.condition.ObjectCondition;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
class AVG implements Query{
@Override
public List query(ListInputStream in) throws SofofException {
List students = in.read("students", Student.class);
LinkedList maps = new LinkedList();
for(Student student : students){
HashMap studentAverage = new HashMap();
studentAverage.put("name", student.getName());
List<Integer> marks = new Select(Mark.class, "#getMark()").from("marks").where(new ObjectCondition("#getName()", Operation.Equal, student.getName())).query(in);
float sum = 0;
for(int mark : marks){
sum += mark;
}
studentAverage.put("avg", sum/marks.size());
maps.add(studentAverage);
}
return maps;
}
}ما كان غير مألوفٍ لديك هو أنني نفّذت استعلامًا آخر داخل استعلامي بتمرير قارئ القوائم للدالّة query, وذلك طلبًا للسهولة والسّرعة, أمّا ما تبقى الآن فهو إضافة النّصّ التّنفيذيّ لأمرك, وهو بمنتهى السهولة, ويتمّ ذلك عبر الصّفّ ExpressionExecuter عبر الدّالّة الإستاتيكيّة execute, ومبدأ عمل النّصّ التّنفيذيّ هو تنفيذ النّصّ على كائن معيّنٍ يمرر للدالّة execute مع النّصّ التّنفيذيّ الذي سيُنفّذ على الكائن الممرر, وستعيد الدّالّة القيمة التي يعيدها تنفيذ النّصّ التّنفيذيّ على الكائن. توفر النافذة ListOutputStream عدة دوال لكتابة الانتقالات Transaction, وهي startTransaction وتقوم هذه الدالة ببدء الانتقال, وفي حالة إطلاق أي استثناء يجب عليك تنفيذ الدالة rollback والتي ستقوم بإلغاء تأثير كل الأوامر السابقة, أما إن أردت تثبيت التغييرات التي أجريتها فعليك تنفيذ الدالة commit.
تعدّ عمليّة تخصيص الشّروط من أسهل العمليات وأمتعها, فصحيحٌ أنّ الشروط المتوافرة تكفي للاستخدام العادي لكن إنشاء الشّرط الخاص بك مطلبٌ مهمٌّ في حال بناء البرامج المعقّدة, ويعتمد الشّرط على دالّة واحدة تستقبل الكائن الّذي ستنفّذ عليه معايير الشّرط, وذلك الكائن هو الكائن المُستعلم عنه من قاعدة البيانات, والدالة هي check الّتي تعرّفها النافذة Condition, وتعيد تلك الدّالّة صحيحًا في حال انطبق الشّرط على الكائن وخاطئًا في حال لم ينطبق, وإن كنت تقوم ببناء أمرٍ فيمكنك إضافة خاصيّة إضافة الشروط لأوامرك, فبعد كتابة كود الأمر قم بتمرير الكائنات الّتي تناسب أمرك (قد يكونك أمرك استعلامًا كما في Select بحيث تكون الكائنات الّتي تجتاز الشّرط هي المُستعلم عنها, وقد يكون أمرك أمرًا تنفيذيًّا كما في Unbind بحيث تكون الكائنات الّتي تجتاز الشّرط هي الّتي سيتمّ إلغاء ربطها, أو غير ذلك من الحالات) واحدًا واحدًا إلى الدّالّة check التي ستنفّذها على الأمر الّذي مرّره المستخدم إلى أمرك, وبناءً على ما تعيده الدّالّة check قرر ماذا ستفعل بالكائن.
تخصيص المُرتبات هو أبسط العمليّات, فما هو إلا بضعة خطوات وستحظى بمُرتّبك الخاص, أوّل تلك الخطوات هي استخدام النافذة Sorter والّتي لها دالّةٌ وحيدةٌ وهي sort, وتستقبل هذه الدّالّة القائمة الّتي سيتمّ ترتيبها, فما عليك إلا ترتيب تلك القائمة بالشّكل الّذي تريد.