18. تطبيق الويب MVC في بنية ثلاثية الطبقات – المثال 4، Postgres
18.1. قاعدة بيانات Postgres
في هذا الإصدار، سنقوم بتثبيت قائمة الأشخاص في جدول قاعدة بيانات Postgres 8.x [http://www.postgres.org]. فيما يلي، تأتي لقطات الشاشة من عميل EMS PostgreSQL Manager Lite [http://www.sqlmanager.net/fr/products/postgresql/manager]، وهو عميل إدارة مجاني لـ SGBD Postgres.
تسمى قاعدة البيانات [dbpersonnes]. وهي تحتوي على جدول [PERSONNES]:

ستحتوي الجدولة [PERSONNES] على قائمة بالأشخاص الذين تديرهم تطبيق الويب. وقد تم إنشاؤها باستخدام الأوامر التالية:
لن نركز على هذه الجدولة التي تشبه الجدولة [PERSONNES] من نوع Firebird التي تمت دراستها سابقًا. ومع ذلك، تجدر الإشارة إلى أن أسماء الأعمدة والجداول موضوعة بين علامتي اقتباس. علاوة على ذلك، فإن هذه الأسماء حساسة لحالة الأحرف. من الممكن أن يكون هذا النمط من عمل Postgres 8.x قابلاً للتكوين. لم أتعمق في هذه المسألة.
قد تحتوي الجدولة [PERSONNES] على المحتوى التالي:

بالإضافة إلى الجدول [PERSONNES]، تحتوي قاعدة البيانات [dbpersonnes] على كائن يسمى تسلسل ويحمل الاسم [SEQ_ID]. يُصدر هذا المولد أرقامًا صحيحة متتالية سنستخدمها لإعطاء قيمة للمفتاح الأساسي [ID] للفئة [PERSONNES]. لنأخذ مثالاً لتوضيح كيفية عمله:
![]() |
![]() |
يمكن ملاحظة أن القيمة [Next value] للتسلسل [SEQ_ID] قد تغيرت (انقر عليها مرتين + F5 للتحديث):
![]() |
الطلب SQL
يسمح لنا بالحصول على القيمة التالية من التسلسل [SEQ_ID]. سنستخدمها في الملف [personnes-postgres.xml] الذي يجمع الأوامر SQL الصادرة على SGBD.
18.2. مشروع Eclipse للطبقات [dao] و [service]
لتطوير الطبقات [dao] و [service] لتطبيقنا باستخدام قاعدة بيانات Postgres 8.x، سنستخدم مشروع Eclipse [spring-mvc-39] التالي:

المشروع هو مشروع Java بسيط، وليس مشروع ويب Tomcat.
المجلد [src]
يحتوي هذا المجلد على أكواد المصدر للطبقات [dao] و [service]:

قد تكون جميع الملفات التي تحتوي على [postgres] في اسمها قد خضعت أو لم تخضع لتعديل مقارنة بإصدار Firebird. وفيما يلي، نصف الملفات التي تم تعديلها.
مجلد [database]
يحتوي هذا الملف على البرنامج النصي لإنشاء قاعدة بيانات Postgres للأشخاص:
![]()
المجلد [lib]
يحتوي هذا الملف على الأرشيفات اللازمة للتطبيق:
![]() |
تجدر الإشارة إلى وجود برنامج التشغيل jdbc الخاص بـ SGBD Postgres 8.x. جميع هذه الملفات هي جزء من Classpath لمشروع Eclipse.
18.3. الطبقة [dao]
الطبقة [dao] هي التالية:

نقدم فقط التغييرات التي طرأت مقارنة بالإصدار [Firebird].
ملف التعيين [personne-postgres.xml] هو التالي:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<!-- تنبيه - يتطلب Postgresql 8 التهجئة الدقيقة لأسماء الأعمدة
et des tables ainsi que des guillemets autour de ces noms -->
<sqlMap>
<!-- اسم مستعار للفئة [Personne] -->
<typeAlias alias="Personne.classe"
type="istia.st.mvc.personnes.entites.Personne"/>
<!-- جدول التعيين [PERSONNES] - كائن [Personne] -->
<resultMap id="Personne.map"
class="istia.st.mvc.personnes.entites.Personne">
<result property="id" column="ID" />
<result property="version" column="VERSION" />
<result property="nom" column="NOM"/>
<result property="prenom" column="PRENOM"/>
<result property="dateNaissance" column="DATENAISSANCE"/>
<result property="marie" column="MARIE"/>
<result property="nbEnfants" column="NBENFANTS"/>
</resultMap>
<!-- قائمة بجميع الأشخاص -->
<select id="Personne.getAll" resultMap="Personne.map" > select "ID",
"VERSION", "NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS" FROM
"PERSONNES"</select>
<!-- الحصول على شخص معين -->
<select id="Personne.getOne" resultMap="Personne.map" >select "ID",
"VERSION", "NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS" FROM
"PERSONNES" WHERE "ID"=#القيمة#</select>
<!-- إضافة شخص -->
<insert id="Personne.insertOne" parameterClass="Personne.classe">
<selectKey keyProperty="id">
SELECT nextval('"SEQ_ID"') as value
</selectKey>
insert into "PERSONNES"("ID", "VERSION",
"NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS") VALUES(#id#,
#الإصدار#، #اللقب#، #الاسم الأول#، #dateNaissance#، #الزوجة#، #nbEnfants#)
</insert>
<!-- تحديث شخص -->
<update id="Personne.updateOne" parameterClass="Personne.classe"> update
"PERSONNES" set "VERSION"=#الإصدار#+1، "NOM"=#اللقب#، "PRENOM"=#الاسم الأول#،
"DATENAISSANCE"=#dateNaissance#, "MARIE"=#marie#, "NBENFANTS"=#nbEnfants#
WHERE "ID"=#id# و "VERSION"=#version#</update>
<!-- حذف شخص -->
<delete id="Personne.deleteOne" parameterClass="int"> delete FROM
"PERSONNES" WHERE "ID"=#value# </delete>
</sqlMap>
وهو يحتوي على نفس محتوى [personnes-firebird.xml] مع التفاصيل التالية:
- أسماء الأعمدة والجداول موضوعة بين علامتي اقتباس، وهذه الأسماء حساسة لحالة الأحرف
- تغير الترتيب SQL " Personne.insertOne " في الأسطر 34-41. تختلف طريقة إنشاء المفتاح الأساسي باستخدام Postgres عن تلك المستخدمة مع Firebird:
- السطر 36: يوفر الترتيب SQL [SELECT nextval('"SEQ_ID"')] المفتاح الأساسي. صيغة [as value] إلزامية. يمثل [value] المفتاح الذي تم الحصول عليه. سيتم تعيين هذه القيمة إلى حقل الكائن [Personne] المحدد بواسطة السمة [keyProperty] (السطر 35)، وهو هنا الحقل [id].
- يتم تنفيذ الأوامر SQL الخاصة بعلامة <insert> بالترتيب الذي تظهر به. لذلك يتم تنفيذ SELECT قبل INSERT. لذلك، عند إجراء عملية الإدراج، سيتم تحديث الحقل [id] الخاص بالكائن [Personne] بواسطة الأمر SQL SELECT.
- السطور 38-40: إدراج الكائن [Personne]
فئة التنفيذ [DaoImplCommon] للطبقة [dao] هي تلك التي تمت دراستها في الإصدار [Firebird].
تم تعديل تكوين الطبقة [dao] لتتوافق مع SGBD و [Postgres]. وبالتالي، فإن ملف التكوين [spring-config-test-dao-postgres.xml] هو كما يلي:
<?xml version="1.0" encoding="ISO_8859-1"?>
<!DOCTYPE beans SYSTEM "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- مصدر البيانات DBCP -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>org.postgresql.Driver</value>
</property>
<property name="url">
<value>jdbc:postgresql:dbpersonnes</value>
</property>
<property name="username">
<value>postgres</value>
</property>
<property name="password">
<value>postgres</value>
</property>
</bean>
<!-- SqlMapCllient -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="configLocation">
<value>classpath:sql-map-config-postgres.xml</value>
</property>
</bean>
<!-- فئة الوصول إلى الطبقة [dao] -->
<bean id="dao" class="istia.st.mvc.personnes.dao.DaoImplCommon">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>
</beans>
- الأسطر 5-19: يشير bean [dataSource] الآن إلى قاعدة البيانات [Postgres] [dbpersonnes] التي يكون مسؤولها هو [postgres] بكلمة مرور [postgres]. سيقوم القارئ بتعديل هذا التكوين وفقًا لبيئته الخاصة.
- السطر 31: الفئة [DaoImplCommon] هي فئة تنفيذ الطبقة [dao]
بعد إجراء هذه التعديلات، يمكننا الانتقال إلى الاختبارات.
18.4. اختبارات الطبقات [dao] و [service]
اختبارات الطبقات [dao] و [service] هي نفسها التي أجريت على الإصدار [Firebird]. لنقم بتشغيل SGBD Postgres ثم اختبارات Eclipse. النتائج التي تم الحصول عليها هي كما يلي:
![]() |
نلاحظ أن الاختبارات قد نجحت مع التنفيذ [DaoImplCommon]. لن نضطر إلى اشتقاق هذه الفئة كما كان ضروريًا مع SGBD و [Firebird].
18.5. اختبارات تطبيق [web]
لاختبار تطبيق الويب باستخدام SGBD و [Postgres]، نقوم بإنشاء مشروع Eclipse [mvc-personnes-04B] بطريقة مشابهة لتلك المستخدمة لإنشاء مشروع [mvc-personnes-03B] باستخدام قاعدة بيانات Firebird (انظر الفقرة 17.7). ومع ذلك، لا يتعين علينا إعادة إنشاء الأرشيفين [personnes-dao.jar] و [personnes-service.jar]. في الواقع، لم نقم بتعديل أي فئة فيما يتعلق بمشروع [mvc-personnes-03B]. ببساطة، يحتوي الأرشيف [personnes-dao.jar] على الفئة [DaoImplFirebird] التي أصبحت عديمة الفائدة.

نقوم بنشر مشروع الويب [mvc-personnes-04B] داخل Tomcat:
![]() | ![]() |
نحن جاهزون لإجراء اختبارات . يصبح محتوى الجدول [PERSONNES] كما يلي:

تم تشغيل Tomcat. باستخدام متصفح، نطلب عنوان URL [http://localhost:8080/mvc-personnes-04B]:

نضيف شخصًا جديدًا عبر الرابط [Ajout]:
![]() | ![]() |
نتحقق من الإضافة في قاعدة البيانات:

يُطلب من القارئ إجراء اختبارات أخرى [modification, suppression].








