نمط السجل النشط

في هندسة البرمجيات ، يُعد نمط السجل النشط نمطًا معماريًا . ويُستخدم في البرامج التي تخزن بيانات الكائنات في الذاكرة ضمن قواعد البيانات العلائقية . وقد أطلق عليه مارتن فاولر هذا الاسم في كتابه " أنماط هندسة تطبيقات المؤسسات" الصادر عام 2003. [ 1 ] [ 2 ] تتضمن واجهة الكائن المتوافق مع هذا النمط وظائف مثل الإدراج والتحديث والحذف، بالإضافة إلى خصائص تُطابق بشكل مباشر أو غير مباشر أعمدة جدول قاعدة البيانات الأساسية.

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

يُستخدم هذا النمط بشكل شائع في أدوات حفظ الكائنات وفي ربط الكائنات بالعلاقات (ORM). عادةً، تُعرض علاقات المفتاح الخارجي ككائن من النوع المناسب عبر خاصية معينة.

التطبيقات

يمكن إيجاد تطبيقات لهذا المفهوم في أطر عمل متنوعة لبيئات برمجة متعددة. على سبيل المثال، إذا كان هناك جدول partsفي قاعدة بيانات يحتوي على عمودين name(من نوع نصي) و price(من نوع رقمي)، وتم تطبيق نمط السجل النشط في الفئة Part، فإن الشفرة الزائفة

Part part = new Part ( "Sample part" , 123.45 );

سيقوم بإنشاء صف جديد في partsالجدول بالقيم المعطاة، وهو ما يعادل تقريبًا أمر SQL

INSERT INTO parts ( name , price ) VALUES ( 'Sample part' , 123 . 45 );

وعلى العكس من ذلك، يمكن استخدام الفئة للاستعلام عن قاعدة البيانات:

الجزء ب = أجزاء . دفق () . تصفية ( p -> "علبة التروس" . يساوي ( p . اسم ())) . البحث عن أول () . أو وإلا ( لا شيء 

سيؤدي هذا إلى العثور على Partكائن جديد بناءً على أول صف مطابق من partsالجدول الذي nameيحتوي عموده على القيمة "gearbox". قد يكون أمر SQL المستخدم مشابهًا لما يلي، وذلك اعتمادًا على تفاصيل تنفيذ SQL لقاعدة البيانات:

SELECT * FROM parts WHERE name = 'gearbox' LIMIT 1 ; -- MySQL أو PostgreSQL

تُطبّق العديد من المكتبات إطار عمل نمط السجل النشط، مثل مكتبات POCO C++ في المكتبة Poco::ActiveRecord. [ 3 ]

مثال

هذا مثال بسيط لكائن سجل نشط Userفي جافا . هنا، Userيمثل الصنف كلاً من النموذج وكائن الوصول إلى البياناتsave() ، ويوفر طرقًا مثل find()و و delete().

package org.wikipedia.examples ;استيراد java.sql.Connection ؛ استيراد java.sql.DriverManager ؛ استيراد java.sql.PreparedStatement ؛ استيراد java.sql.ResultSet ؛ استيراد java.sql.SQLException ؛ استيراد java.sql.Statement ؛public class User { private int id ; private String name ; private String email ;public User ( String name , String email ) { this . name = name ; this . email = email ; }public int getId () { return id ; }public void setId ( int id ) { this . id = id ; }public String getName () { return name ; }public void setName ( String name ) { this . name = name ; }public String getEmail () { return email ; }public void setEmail ( String email ) { this . email = email ; }public void save ( ) { try ( Connection conn = DriverManager.getConnection ( " jdbc : mysql ://localhost:3306/mydb" , " user " , " password " ) ) { if ( this.id == 0 ) { String sql = " INSERT INTO users ( name , email) VALUES (?, ? ) " ; try ( PreparedStatement stmt = conn.preparedStatement ( sql , Statement.RETURN_GENERATED_KEYS ) ) { stmt.setString ( 1 , this.name ) ; stmt.setString ( 2 , this.email ) ; stmt.executeUpdate ( ) ; ResultSet rs = stmt.getGeneratedKeys ( ) ; if ( rs.next ( ) ) { this.id = rs.getInt ( 1 ) ; } } } else { String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?" ; try ( PreparedStatement stmt = conn . prepareStatement ( sql )) { stmt . setString ( 1 , this . name ); stmt . setString ( 2 , this . email ); stmt . setInt ( 3 , this . id ); stmt . executeUpdate (); } } } catch ( SQLException e ) { System . err . printf ( "حدث خطأ SQL: %s%n" , e .getMessage ()); e.printStackTrace ( ) ; } }public static User find ( int id ) { try ( Connection conn = DriverManager.getConnection ( " jdbc :mysql://localhost:3306/mydb" , " user" , " password" )) { String sql = "SELECT * FROM users WHERE id = ?" ; try ( PreparedStatement stmt = conn.preparedStatement ( sql ) ) { stmt.setInt ( 1 , id ); ResultSet rs = stmt.executeQuery (); if ( rs.next ( ) ) { User user = new User ( rs.getString ( " name " ) , rs.getString ( " email " ) ) ; user.setId ( rs.getInt ( " id " ) ) ; return user ; } } } catch ( SQLException e ) { System.err . printf ( "حدث خطأ SQL: %s%n" , e.getMessage ( )) ; e.printStackTrace ( ) ; } return null ; }public void delete ( ) { try ( Connection conn = DriverManager.getConnection ( "jdbc:mysql://localhost:3306/mydb" , " user " , " password" )) { String sql = "DELETE FROM users WHERE id = ?" ; try ( PreparedStatement stmt = conn.preparedStatement ( sql ) ) { stmt.setInt ( 1 , this.id ) ; stmt.executeUpdate ( ) ; } } catch ( SQLException e ) { System.err.printf ( " حدث خطأ SQL: % s % n " , e.getMessage ( ) ) ; e.printStackTrace ( ) ; } } }

نقد

مبدأ المسؤولية الواحدة وفصل الاهتمامات

من الانتقادات الأخرى الموجهة لنمط السجل النشط أنه، نظرًا للترابط الوثيق بين تفاعل قاعدة البيانات ومنطق التطبيق، لا يلتزم كائن السجل النشط بمبدأ المسؤولية الواحدة وفصل الاهتمامات . وهذا يتناقض مع بنية الطبقات المتعددة التي تعالج هذه الممارسات بشكل صحيح. ولهذا السبب، يُعد نمط السجل النشط الأنسب والأكثر استخدامًا في التطبيقات البسيطة التي تعتمد كليًا على نماذج البيانات مع وظائف CRUD ، أو كجزء من بنية معينة. وعادةً ما يكون هذا الجزء هو الوصول إلى البيانات، وهذا هو سبب تطبيق العديد من أنظمة إدارة قواعد البيانات العلائقية (ORM) لنمط السجل النشط.

انظر أيضاً

مراجع

  1. صفحة من كتالوج EAA - سجل نشط
  2. فاولر، مارتن (2003). أنماط هندسة تطبيقات المؤسسات . أديسون-ويسلي. ISBN 978-0-321-12742-6.
  3. "مساحة الاسم Poco::ActiveRecord" . docs.pocoproject.org . مشروع POCO . تم الاطلاع عليه بتاريخ 18 أكتوبر 2025 .