الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

من تصميمي: حزمة ObjectDatabase لتحويل SQL إلى OOP

بدأه حسام الملحم في 8 فبراير 2006 · 9 رد · 3,058 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

السلام عليكم ورحمة الله وبركاته

إليكم الإصدار 1.0 من حزمة ObjectDatabase

هذه الحزمة سوف تقدم لك خدمة تسهيل التعامل مع قواعد البيانات بصورة كائنات متعلقة ببعضها.

هذه الحزمة ليست موجهة للمستخدم العادي وإنما موجهة للمطور الذي يريد أن يبني تطبيقا لأحد عملاءه.

سأقوم بشرح طريقة الاستخدام للمطور المبتدئ العادي (الذي يريد استخدام الحزمة مباشرة) وأقوم في تعقيب لاحق ذكر توجيهات للمطور المتقدم في هندسة الأشياء أو OOP!

هذه الحزمة تقدم للمطور وسيلة إلى قولبة قاعدة البيانات في نظام شيئي التوجه. سيكون لديك قاعدة بيانات على شكل SQLDataSource، وسيكون لديك RecordHome والتي تمثل جدولا في قاعدة بياناتك، وسيكون لديك Record والتي تمثل صفا أو Row من البيانات داخل إحدى جداولك.

ملاحظة: كي تستفيد من قوة هذه الحزمة، ينصح باستخدام قواعد بيانات MySQL أو قواعد بيانات أقوى. تستطيع أن تستخدم Access لكن عليك أن تقوم بخطوات زيادة على ما سأقدم.

------

افرض أن لديك قاعدة بيانات بنك معين تحمل الجداول Customer و Account وغيرها.

هذه قاعدة البيانات banksystem

هذا جدول Customer:

08_02_06_02_24_40_1139394280CustomerTable.GIF

وهذا جدول Account:

08_02_06_02_25_41_1139394341AccountTable.GIF

لاحظ أن الحقل customer_id هو مفتاح أجنبي موصول إلى id في Customer.

بعد أن تصمم جدولين كهذين الجدولين وتعين المفاتيح الأساسية والثانوية أو الأجنبية Primary, Foreign Keys، نستخدم حزمتنا مباشرة لقراءة الجداول مع علاقاتها مباشرة:

public static void test()throws Exception{
  Class.forName("com.mysql.jdbc.Driver");//مناسب Jdbc تحميل
  ConnectionPool pool=new ConnectionPool("jdbc:mysql://localhost/banksystem","root", "admin",10);//تكوين اتصال مع قاعدة البيانات، وتوفير مسبح للاتصالات يحوي 10 اتصالات جاهزة.
  TablesDataSource source=new SQLDataSource(pool);//يقرأ قاعدة البيانات مع كل تفاصيلها مثل جداولها والمفاتيح الأساسية والثانوية أو الأجنبية
  
  RecordHome home=source.lookup("account");//نستدعي جدول الحسابات
  Record r=home.load(2);//أحضر الحساب ذو الرقم التسلسلي 2
  System.out.println ("Balance: "+r.getEntry("balance"));//اطبع الميزانية للحساب
  Record r2=(Record)r.getRecord("customer_id");//أحضر بيانات العميل صاخب هذا الحساب
  System.out.println ("Name of Customer: "+r2.getEntry("name"));//اطبع اسم العميل
  //مثال آخر
  RecordHome customers=source.lookup("customer");//أحضر جدول العملاء
  Record c=customers.load(1);// أحضر العميل صاحب الرقم 1
  c.setEntry("username", "ObjectDatabase User Name ");//غير قيمة اسم الدخول إلى التالي
  customers.update(c);//ثبت التغيير في الجدول
  
  pool.close();//أغلق الاتصال
	}

الشفرة السابقة تقرأ من جدول وتنتقل إلى بيانات من جدول آخر بكل سهولة. لاحظ أننا انتقلنا من account إلى customer لوجود Foriegn key في الجدول account.

انظر إلى شرح الفئات:

DatabaseRecord

DatabaseRecordHome

SQLDataSource

شرح الحزمة ObjectDatabase بالكامل

كما ترى، عندك أوامر SQL جاهزة في داخل كل من الأوامر load و update و find و save والتي تعكس الأوامر المعروفة Insert و select وغيرها. لكنك في النهاية تخلصت من SQL العادية وانتقلت إلى برمجية شيئية التوجه.

فأنت سيكون عندك Record تمثل صفا في الجدول customer وعندها تستطيع أن تعرف كل الحسابات التي عند customer باستعمال الأوامر find مثلا. لاحظ أن النتيجة ستكون List<Record> rs يعني تحكم مباشر في النتائج!

كي تستخدم الحزمة حمل المكتبة من صفحتي:

تحميل مكتبة ObjectDatabase

الإصدارات الجديدة سوف تكون في هذه الصفحة.

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

حاليا: تستطيع تجربتها مع أي قاعدة بيانات صنعتها قديما بـ MySQL. وأخبرني بالنتائج.

في المرفق قاعدة بيانات MySQL تمثل banksystem بسيط. تستطيع تجربة هذه القاعدة أو أي قاعدة بيانات عندك مع هذه الحزمة:

banksystem.zip

تم تعديل هذه المشاركة بواسطة أبومازن في 8 فبراير 2006 في 15:16

#2

يدرك الكثير ما لقواعد البيانات من أهمية كبيرة في البرامج التجارية والمؤسسية والمنظمات الحكومية، ويبرز دور تطوير تسهيلات وصناعة حزم لسرعة تطوير برمجيات تقوم في خدمة المطور بطريقة سريعة ودقيقة. ولا يخفى على الجميع أهمية الدقة والثبات في التحكم بالبيانات المتعلقة بهذه المنظمات.

كي تفهم هذا الموضوع جيدا: يتطلب منك معرفة الآتي:

1- معرفة في تصميم قواعد البيانات، مع الأخذ بالاعتبار المفاتيح الأساسية والصديقة (Primary Keys + Foreign Keys)

2- معرفة في لغة الجافا.

3- معرفة في JDBC وهي النافذة التي من خلالها تطلق أوامر SQL.

--------------------

نبذة عن المشكلة التي نريد حلها التي من أجلها صممت هذه الحزمة:

من المعلوم أن قراءة البيانات من ResultSet الناتجة من جملة SQL عن طريق تنفيذ Statement أو PreparedStatement هي عملية مباشرة يتم فيها قراءة البيانات من القاعدة بصورة أولية. وأقصد بهذا أن الناتج هو مجموعة من البيانات المفرقة كالكلمات والأرقام والتواريخ وربما جزيئات Bits أخرى. بعد ذلك يتعامل المطور مع هذه البيانات مباشرة.

ولو افترضنا أن المطور سينظم عمله، لقلب هذه البيانات ResultSet إلى فئات معينة تترجم أو تحاكي منطق برنامجه. فهو سيصنع فئة Customer وفئة أخرى Account مثلا وغيرها حسب الحاجة. طبعا سيضطر إلى نقل هذه المعلومات من وإلى قاعدة البيانات بصورة ResultSet وجمل PreparedStatement.

توجد عدة مشاكل في الصورة التي افترضناها والتي تواجهني شخصيا، هي ليست مشاكل ولكنها مصاعب أريد تسهيلها وأصبغها صبغة البرمجة الشيئية. فالمطور لا يريد أن يتعامل مع البيانات بصورة بيانات منفصلة في هيئة ResultSet، بل هو يريد أن يتعامل معها بصورة أشياء أو Objects، مثل Customer، Account, Transfer, Rent, وغيرها من المنظومات. وحبذا لو وجدت قواعد بيانات شيئية التوجه متوفرة وسهلة الاستخدام، ولكن كما يعلم الباحث أن قواعد البيانات OODBMS لم تنضج بعد. ولهذا صممت هذه الحزمة لمحاكاة قواعد البيانات الشيئية التوجه التي لطالما حلمنا بها!

من المشاكل الأخرى التي يواجهها المطور هو التحكم بالبيانات من خيوط أو Threads متفرقة. افرض مثلا أن لديك برنامج يعمل على Tomcat أو web server بمعنى آخر، ولديك عدة مستخدمين، وأراد 2 منهم أن يغيروا أو يتعاملوا مع بيان واحد في هذه القاعدة في نفس الوقت،، المشكلة تظهر عندما يستقبل كل عميل ResultSet مختلف يحملان نفس البيانات، ويقومان كليهما بمحاولة تغيير هذا البيان. أو ربما يقوم برنامجك بصناعة Customer جديد لكل منهم مع أنه نفس Customer. أقصد بهذا هي المشكلة المعروفة في الحفظ والتعديل من قبل مستخدمين في نفس الوقت.

الحزمة ستحل المشكلة السابقة، فلو حملت بيانات معينة مرتين، فسيستقبل المستخدمين نفس البيانات وليست نسختين من نفس البيانات.

Class.forName("com.mysql.jdbc.Driver");//مناسب Jdbc تحميل
 ConnectionPool pool=new ConnectionPool("jdbc:mysql://localhost/banksystem","root", "admin",10);//تكوين اتصال مع قاعدة البيانات، وتوفير مسبح للاتصالات يحوي 10 اتصالات جاهزة.
 TablesDataSource source=new SQLDataSource(pool);

RecordHome customerTable=source.lookup("customer");
Record c1=customerTable.load(1); // قراءة بيانات عميل من قاعدة البيانات.
Record c2=customerTable.load(1);// قراءة بيانات نفس العميل مرة أخرى.
System.out.println(c1==c2); // الناتج هو صحيح أو 
true.

ماذا يعني هذا؟؟ يعني هذا أنه عندما تقرأ من قاعدة البيانات نفس المعلومات فإن الحزمة سترجع لك نفس Record المصنوع أول مرة، ولن تنشئ Record جديد لنفس المعلومات! الحزمة لن تحمل بيانات جديدة ولن تصنع new Record إذا كانت هذه البيانات موجودة في الذاكرة!

ليس هذا فقط! افرض أنك تريد أن تسجل عملية خصم مبلغ من حساب معين إذا توفر هذا المبلغ في الحساب! إن التعامل مع ResultSet و PreparedStatement مباشرة لن يمكنك من التحكم بالخصم إذا تعددت الخيوط التي تريد الخصم. (الأمر الذي قد يؤدي إلى خصم المبلغ حتى لو كان في الحساب مبلغا بسيطا.

لكن في هذه الحزمة تستطيع الحجر على الحساب المقصود وتقوم بحسم المبلغ.

double debitAmount=1000;
RecordHome accounts=source.lookup("account");
Record acct=accounts.load(1);
synchronized(acct){
double balance = (Double)acct.getEntry("balance");
if(balance> debitAmount){
acct.setEntry("balance", balance-debitAmount);
accounts.update(acct);
}else{
throw new Exception("You dont have enough funds");
}
}

لاحظ أنك تقفل فقط حسابا واحدا وتقوم بالخصم منه إذا كان يحوي أكثر من المراد خصمه. ولو تعددت الطلبات على خصم المبلغ فلن تقع مشكلة لأنك أقفلت الحساب الذي تريد الخصم منه باستعمالك ل synchronized.

هذه من أكبر المشاكل التي يواجهها المتعامل مع قاعدة البيانات. وقد حلت بنظافة، وهي ثابتة بإذن الله للتعامل معها في بيئة متعددة الخيوط أو multithreaded. ربما تقول لي أنك تقفل الاتصال لأكمله لتنفيذ هذه العملية، لكني أقول لك أن قفل الاتصال بأكمله سيجعل برنامجك بطيئا نسبيا في استقبال الطلبات من العملاء.

ربما تخبرني بوجود Enterprise Java Beans أو EJB، لكنها متوفرة فقط Application Server مثل Sun أو JBoss. لكنك تريد أن تتعامل مع البيانات كهيئة أشياء في محيطك الآخر مثل استعمالك فقط لـ Web Container أو برنامج على سطح المكتب عادي. كما أنك قد تريد أن تستخدم قواعد بيانات هندسية لثباتها وسرعتها مقارنة لقواعد البيانات الشيئية التوجه.

#3

بصراحة شيء رائع جدا ، أخي أبو مازن ،،،

كنت أبحث عن مثل هذه الحزمة لأستخدمها في مشاريعي ...

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

لا أدري هل توجد هذه الإمكانية ،،

لأني أفكر لو أني عندي عدة جداول و أردت أن أعمل لها واجهات رسومية ،، ولكن أردت أن أعمل شريط يقوم بالمهمات السابقة :

الأول - السابق - التالي - الأخير - حفظ - إلغاء

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

#4

ملاحظة بعض المشاركات حذفت بسبب خادم المنتدى.

قد أشرت في المشاركات المحذوفة أن هذه الحزمة ليست وظيفتها الاستغناء عن SQL، وإنما هي تنظيم الحصول على النتائج، عدم تكرار البيانات الناتجة، واستخدام شيئي التوجه مع البيانات، والقدرة على قفل البيانات للتحكم فيها في حالة تعدد الخيوط Multithreding.

أحب التنويه أن هذه الحزمة ثابتة للاستخدام والله أعلم، وقد أرفقت نسخة تحديث إلى صفحتي للتأكد من جودتها.

سأنتقل إلى مثال حيوي:

نريد أن نحصل على أول 50 بيان من الجدول Customer

import edu.hussam.database.sql*;
//code
Class.forName("SQL Driver");
ConnectionPool pool=new ConnectionPool(........);
SQLDataSource source=new SQLDataSource(pool);
PreparedConnection con=pool.getConnection();
Statement s=con.getConnection().createStatement();
ResultSet result=s.executeQuery("SELECT * FROM Customer Limit 1 - 50;");
DatabaseRecordHome customerTable= source.lookup("customer");
List<? extends Record> customers= customerTable.build(result);

//أصبح لديك مجموعة تحوي البيانات التي تريد عرضها! تستطيع وضعها في جدول وتستطيع أن تصممها وتضع سابق ولاحق!

عندما تصبح لديك هذه المجموعة List،، تستطيع أن ترسلها إلى واجهة رسومية تقوم بعرض كل Record في صفحة.. أو اعرضها كيف تشاء.

لاحظ أنك تستطيع أن ترسل ما تشاء من أوامر SQL وعندها تقوم بفرزها لتحويلها إلى أشياء يمكنك نقلها بسهولة في برنامجك على هيئة Record!

هل الفكرة واضحة أخي فهد؟ أرجو أن تجربها...

#5

لاحظ هذه الأمور:

1- عليك أن تصمم قاعدة البيانات بطريقة صحيحة. عليك بالانتباه إلى أن كل جدول يحوي Primary Key،، وأن تحرص على وضع Forigen Key كما ينبغي!

2- إذا حصلت على Record عندك الأوامر:

Strnig  email = record.getEntry("email");
record.setEntry("email", "myNewEmail@team.com");
recordHome.update(record);

إذا أردت أن تحصل على Record آخر من جدول آخر متعلق بـ Foriegn Key استخدم:

String foreignKeyName = "department";
Record department = record.toRecord(foreignKeyName);
String deptName =(String) department.getEntry("name");
#6

جميل جدا أخي أبو مازن ،،،،

سوف أستخدم هذه الحزمة إن شاء الله في المشروع الذي سوف أعرضه في المنتدى قريبا ، وهو يتعلق بقواعد البيانات ...

#7

وين راح ردي!!! هذا المشرف الشرير هو اللي حذفه

Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why

#8

ايش رايك بهل الكلام...

Caché, the multidimensional database, lets developers create and persist Java objects – while automatically providing SQL access to data. Plus, Caché projects classes as EJB components with bean-managed persistence.

Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why

#9

كلام جميل يا رامي،، لم أجربها... وانقطعت قليلا عن هذا المشروع...

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

ObjectDatabase جعلته في sourceForge لمن أراد أن يجرب الحزمة أو أن يساعد في تطويرها إن لزم الأمر:

https://sourceforge.net/projects/objectdatabase/

باستعمال خدمات CVS من sourceForge نستطيع أن نطور الحزمة جماعيا دون أن يؤثر أحدا على الآخر.. وضعت الشفرات في الموقع وسنتعامل مع الملفات عن بعد وبصورة جماعية لمن يريد.

حاليا: أستخدم Netbeans للدخول على sourceForge،، فأنا أدخل على sourceForge وأحرر الملفات وترجع إلى الخادم بصورة ذاتية تقريبا وسهلة.

#10

السلام عليك

إن فكرة المشروع جميلة جدا و لكن هنا بيئة عمل قوية و تؤدي جميع الاحياجات تدعى

hibernet

بمكنك من خلال هذه البيئة برمجة قواعد البيانات بشكل غرضي التوجه فكل سطر في جدول هو عبارة عن غرض

كما تتتع باستقلالية عن محركات الدات بيز أي بكل بساطة نفس برنامج الجاف يمكن أن يعمل على ما يقارب من 23 قاعدة بيانات من دون أن تغير شئ في الكود إلا شيئ بسيط

كما أنها تدعم

transaction,security,..

مواضيع مشابهة