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

ربط قاعدة بيانات MySQL مع برنامج Java و قراءة البرنامج للبيانات الموجودة داخل هذه القاعدة

بدأه issam-ahmed في 24 ديسمبر 2011 · 8 رد · 4,727 مشاهدة · في JavaEE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

إخواني الكرام،،،،

يوجد في كتاب How to programe Java مثال عن ربط جافا مع قاعدة بيانات و قمت بتنزيل MySQL و نسخت الكود في برنامج النت بينز لكن بيعطيني

خطأ على حاجة إسمها ResultSetTableModel و على الإستثنائات الموجودة في البرنامج و لا يعطي نتيجة البرنامج أي لا يقرأ من قاعدة البيانات .

الكود بالكامل :



/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package displayqueryresults;

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.sql.SQLException;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.JTable;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import javax.swing.Box;


public class DisplayQueryResults extends JFrame
{
// JDBC driver, database URL, username and password
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DATABASE_URL = "jdbc:mysql://localhost/books";
static final String USERNAME= "jhtp6";
static final String PASSWORD= "jhtp6";

// default query retrieves all data from authors table
static final String DEFAULT_QUERY = "SELECT * FROM authors";


private ResultSetTableModel tableModel;
private JTextArea queryArea;

// create ResultSetTableModel and GUI
public DisplayQueryResults()
{
super( "Displaying Query Results" );

// create ResultSetTableModel and display database table
try
{
// create TableModel for results of query SELECT * FROM authors
tableModel = new ResultSetTableModel( JDBC_DRIVER, DATABASE_URL,
USERNAME, PASSWORD, DEFAULT_QUERY );

// set up JTextArea in which user types queries
queryArea = new JTextArea( DEFAULT_QUERY, 3, 100 );
queryArea.setWrapStyleWord( true );
queryArea.setLineWrap( true );

JScrollPane scrollPane = new JScrollPane( queryArea,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );

// set up JButton for submitting queries
JButton submitButton = new JButton( "Submit Query" );

// create Box to manage placement of queryArea and
// submitButton in GUI
Box box = Box.createHorizontalBox();
box.add( scrollPane );
box.add( submitButton );

// create JTable delegate for tableModel
JTable resultTable = new JTable( tableModel );

// place GUI components on content pane
add( box, BorderLayout.NORTH );
add( new JScrollPane( resultTable ), BorderLayout.CENTER );

// create event listener for submitButton
submitButton.addActionListener(

new ActionListener()
{
// pass query to table model
public void actionPerformed( ActionEvent event )
{
// perform a new query
try
{
tableModel.setQuery( queryArea.getText() );
} // end try
catch ( SQLException sqlException )
{
JOptionPane.showMessageDialog( null,
sqlException.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );

// try to recover from invalid user query
// by executing default query
try
{
tableModel.setQuery( DEFAULT_QUERY );
queryArea.setText( DEFAULT_QUERY );
} // end try
catch ( SQLException sqlException2 )
{
JOptionPane.showMessageDialog( null,
sqlException2.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );

// ensure database connection is closed
tableModel.disconnectFromDatabase();

System.exit( 1 ); // terminate application
} // end inner catch
} // end outer catch
} // end actionPerformed
} // end ActionListener inner class
); // end call to addActionListener

setSize( 500, 250 ); // set window size
setVisible( true ); // display window
} // end try
catch ( ClassNotFoundException classNotFound )
{
JOptionPane.showMessageDialog( null,
"MySQL driver not found", "Driver not found",
JOptionPane.ERROR_MESSAGE );

System.exit( 1 ); // terminate application
} // end catch
catch ( SQLException sqlException )
{
JOptionPane.showMessageDialog( null, sqlException.getMessage(),
"Database error", JOptionPane.ERROR_MESSAGE );

// ensure database connection is closed
tableModel.disconnectFromDatabase();

System.exit( 1 ); // terminate application
} // end catch

// dispose of window when user quits application (this overrides
// the default of HIDE_ON_CLOSE)
setDefaultCloseOperation( DISPOSE_ON_CLOSE );

// ensure database connection is closed when user quits application
addWindowListener(

new WindowAdapter()
{
// disconnect from database and exit when window has closed
public void windowClosed( WindowEvent event )
{
tableModel.disconnectFromDatabase();
System.exit( 0 );
} // end method windowClosed
} // end WindowAdapter inner class
); // end call to addWindowListener
} // end DisplayQueryResults constructor

// execute application
public static void main( String args[] )
{
new DisplayQueryResults();
} // end main
} // end class DisplayQueryResults


الأجزاء الذي تعرف عليها البرنامج كخطأ هي



private ResultSetTableModel tableModel;

و بالتالي أي شيء يعتمد على هذه الجملة .

بالإضافة إلى جميع الإستثنائات في البرنامج و هي كالتالي :




catch ( SQLException sqlException )
{
JOptionPane.showMessageDialog( null,
sqlException.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );





catch ( SQLException sqlException2 )
{
JOptionPane.showMessageDialog( null,
sqlException2.getMessage(), "Database error",
JOptionPane.ERROR_MESSAGE );

// ensure database connection is closed
tableModel.disconnectFromDatabase();

System.exit( 1 ); // terminate application
}



catch ( ClassNotFoundException classNotFound )
{
JOptionPane.showMessageDialog( null,
"MySQL driver not found", "Driver not found",
JOptionPane.ERROR_MESSAGE );

System.exit( 1 ); // terminate application
}





catch ( SQLException sqlException )
{
JOptionPane.showMessageDialog( null, sqlException.getMessage(),
"Database error", JOptionPane.ERROR_MESSAGE );

// ensure database connection is closed
tableModel.disconnectFromDatabase();

System.exit( 1 ); // terminate application
}

طبعاً الخطأ على السطر الأول من كل فقرة .

أتمنى أن تساعدوني بحل المشكلة و بارك الله فيكم .

#2

السلام عليكم ..

  1. من هتا يمكنك تحميل أمثلة الكتاب Deitel and Deitel, Java - How to Program - 6th Ed رابط
  2. كود الصفوف التي ذكرتها موجودة في ch25 ... و منها ResultSetTableModel.java
  3. و المفروض أنك تنشئ قاعدة البيانات المطلوبة و فيها الجداول المطلوبة .. اعتقد أنها موجودة بالملف books.sql أو الملف employees.sql
1

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#3
houssam11350_11350 كتب:

السلام عليكم ..

  1. من هتا يمكنك تحميل أمثلة الكتاب Deitel and Deitel, Java - How to Program - 6th Ed رابط
  2. كود الصفوف التي ذكرتها موجودة في ch25 ... و منها ResultSetTableModel.java
  3. و المفروض أنك تنشئ قاعدة البيانات المطلوبة و فيها الجداول المطلوبة .. اعتقد أنها موجودة بالملف books.sql أو الملف employees.sql

مشكور أخي الكريم، تم إضافة لكلاس الجديدة و هي ResultSetTableModel و البرنامج إشتغل 100 % لكن لدي بعض إستفسارت

و تعقيبات على كود البرنامج هل من الممكن أن أضعها هنا ؟ أم أفتح موضوع جديد ؟ لأنه لا أدري مخالف أن أضع الإستفسارات هنا أم لا ؟

و شكراً لك.

#4

السلام عليكم ..

  1. ممكن تضع الاستفسار هنا .. و إذا لم تجد جوابك افتح موضوع جديد ..
  2. تذكر فقط قوانين المنتدى بأنه يمنع حل الواجبات و طلب الكراكات .. و غيرها ..

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#5

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

شكراً لك أخي الكريم ،، و أسف جداً على تأخري بمتابعة ما طرحت .

بالنسبة للإستفسارات أولاً سأضيف هنا الكود الخاص بالكلاس الأخرى و هي تعتبر نصف البرنامج تقريباً



// Fig. 25.28: ResultSetTableModel.java
// A TableModel that supplies ResultSet data to a JTable.
package displayqueryresults;

import java.sql.Connection;
import java.sql.Statement;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import javax.swing.table.AbstractTableModel;

// ResultSet rows and columns are counted from 1 and JTable
// rows and columns are counted from 0. When processing
// ResultSet rows or columns for use in a JTable, it is
// necessary to add 1 to the row or column number to manipulate
// the appropriate ResultSet column (i.e., JTable column 0 is
// ResultSet column 1 and JTable row 0 is ResultSet row 1).
public class ResultSetTableModel extends AbstractTableModel
{
private Connection connection;
private Statement statement;
private ResultSet resultSet;
private ResultSetMetaData metaData;
private int numberOfRows;

// keep track of database connection status
private boolean connectedToDatabase = false;

// constructor initializes resultSet and obtains its meta data object;
// determines number of rows
public ResultSetTableModel( String driver, String url,
String username, String password, String query )
throws SQLException, ClassNotFoundException
{
// load database driver class
Class.forName( driver );

// connect to database
connection = DriverManager.getConnection( url, username, password );

// create Statement to query database
statement = connection.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY );

// update database connection status
connectedToDatabase = true;

// set query and execute it
setQuery( query );
} // end constructor ResultSetTableModel

// get class that represents column type
public Class getColumnClass( int column ) throws IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

// determine Java class of column
try
{
String className = metaData.getColumnClassName( column + 1 );

// return Class object that represents className
return Class.forName( className );
} // end try
catch ( Exception exception )
{
exception.printStackTrace();
} // end catch

return Object.class; // if problems occur above, assume type Object
} // end method getColumnClass

// get number of columns in ResultSet
public int getColumnCount() throws IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

// determine number of columns
try
{
return metaData.getColumnCount();
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch

return 0; // if problems occur above, return 0 for number of columns
} // end method getColumnCount

// get name of a particular column in ResultSet
public String getColumnName( int column ) throws IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

// determine column name
try
{
return metaData.getColumnName( column + 1 );
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch

return ""; // if problems, return empty string for column name
} // end method getColumnName

// return number of rows in ResultSet
public int getRowCount() throws IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

return numberOfRows;
} // end method getRowCount

// obtain value in particular row and column
public Object getValueAt( int row, int column )
throws IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

// obtain a value at specified ResultSet row and column
try
{
resultSet.absolute( row + 1 );
return resultSet.getObject( column + 1 );
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch

return ""; // if problems, return empty string object
} // end method getValueAt

// set new database query string
public void setQuery( String query )
throws SQLException, IllegalStateException
{
// ensure database connection is available
if ( !connectedToDatabase )
throw new IllegalStateException( "Not Connected to Database" );

// specify query and execute it
resultSet = statement.executeQuery( query );

// obtain meta data for ResultSet
metaData = resultSet.getMetaData();

// determine number of rows in ResultSet
resultSet.last(); // move to last row
numberOfRows = resultSet.getRow(); // get row number

// notify JTable that model has changed
fireTableStructureChanged();
} // end method setQuery

// close Statement and Connection
public void disconnectFromDatabase()
{
if ( !connectedToDatabase )
return;

// close Statement and Connection
try
{
statement.close();
connection.close();
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch
finally // update database connection status
{
connectedToDatabase = false;
} // end finally
} // end method disconnectFromDatabase
} // end class ResultSetTableModel



و الآن أبدأ على بركة الله في إختيار جزئيات لم أفهمها و أحتاج شرح و لو بسيط عنها :

أحتاج شرح بسيط عن وظيفة ResultSet

نأتي هنا



public class ResultSetTableModel extends AbstractTableModel

ننظر أن ResultSetTableModel هي عبارة عن كلاس تابعة للكلاس الأب و هي AbstractTableModel فهل أمكن تعرفني على AbstractTableModel ؟

ما وظيفة هذه الجملة؟



statement = connection.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY );

في الكود التالي هل connectedToDatabase ميثود جاهزة نستدعيها لكي نغلق إتصالنا مع قاعدة البيانات و لماذا بدأ بهذه الجملة البرنامج



private boolean connectedToDatabase = false;

و ماذا تختلف عن الجمل التالية:



statement.close();
connection.close();

أخيراً هذه جملة تنفيذ الإستعلام



setQuery( query );

*****************

resultSet = statement.executeQuery( query );

لكن السؤال كلمة query تدل على ماذا و هل ملزمين بها دائماً أم بإمكانا نغيرها و نضغ ما نريد ؟

و بارك الله فيكم و أتمنى أن لا أكون قد أسرفت في كتابة الأسئلة و الإستفسارات .

#6

السلام عليكم ..

  1. ResultSet تمثل نتيجة الاستعلام و هي عبارة عن جدول و فيها مؤشر داخلي يشير إلى السطر الحالي من البيانات و يتم استخدام الإجراء next لنقل المؤشر
  2. الــ AbstractTableModel هو صف نقوم بالوراثة منه في الصف الجديد , كي يكون قابلا للإظهار على الفورم على العنصر JTable ..و يجب أن نعيد تعريف الإجرائيات التالية :
    public Class getColumnClass( int column ) throws IllegalStateException
    public int getColumnCount() throws IllegalStateException
    public String getColumnName( int column ) throws IllegalStateException
    public int getRowCount() throws IllegalStateException
    public Object getValueAt( int row, int column )

    و هي الإجرائيات التي تحدد نوع بيانات كل عمود و عدد الأعمدة في الجدول و اسم كل عمود و عدد الأسطر و القيمة في كل خلية و هي المعلومات المطلوبة حتى نظهر أي شئ في الــ JTable ..

  3. الكود :
    statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );

    مهمته إنشاء عبارة statement و نحدد نوعها بأنها scrollable و غير حساسة للتغيرات و انها CONCUR (متعددة الوصول) و لكنها للقراءة فقط .. راجع ResultSet

  4. connectedToDatabase عبارة عن متحول منطقي بولياني يحدد هل تم الأتصال بالقاعدة أو لا .. و يمكن ان تضع له أي اسم ... و في البداية تكون قيمته false أي أننا غير متصلين بالقاعدة بعد .
  5. statement.close(); connection.close(); مهمتها إغلاق العبارة و الوصلة .. و لا يمكن تنفيذ الاستعلامات بعد عملية الإغلاق ..
  6. setQuery هي إجراء مهمته تمرير الاستعلام للعبارة resultSet = statement.executeQuery( query ); و يمكن اختيار أي اسم نريده ... و كمة query ممكن أن نكتب أي اسم نريده .. بسرظ أن نستبدله في كل الأماكن ..

ملاحظات ..

  1. أخي الكريم ...ليس بالضرورة أن تأخذ الأمثلة بحرفيتها .. طالما المطلوب هو التعلم ... فأنت حاول الأتصال بقاعدة البيانات و تنفيذ استعلام و وضع النتيجة في الــ ResultSet ثم طباعتها للخرج باستخدام System.out.println ... لأن موضوع الــ Table Model يعتبر موضوع متقدم نوعا ما .. لكن لا بأس من تعلمه .. لكن في مرحلة متقدمة عندما تبدأ مع عناصر الــ GUI ..
  2. استخدم الــ Java Documentation للقراءة عن الصفوف ..رابط
2

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#7
houssam11350_11350 كتب:

السلام عليكم ..

  1. ResultSet تمثل نتيجة الاستعلام و هي عبارة عن جدول و فيها مؤشر داخلي يشير إلى السطر الحالي من البيانات و يتم استخدام الإجراء next لنقل المؤشر
  2. الــ AbstractTableModel هو صف نقوم بالوراثة منه في الصف الجديد , كي يكون قابلا للإظهار على الفورم على العنصر JTable ..و يجب أن نعيد تعريف الإجرائيات التالية :
    public Class getColumnClass( int column ) throws IllegalStateException
    public int getColumnCount() throws IllegalStateException
    public String getColumnName( int column ) throws IllegalStateException
    public int getRowCount() throws IllegalStateException
    public Object getValueAt( int row, int column )

    و هي الإجرائيات التي تحدد نوع بيانات كل عمود و عدد الأعمدة في الجدول و اسم كل عمود و عدد الأسطر و القيمة في كل خلية و هي المعلومات المطلوبة حتى نظهر أي شئ في الــ JTable ..

  3. الكود :
    statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY );

    مهمته إنشاء عبارة statement و نحدد نوعها بأنها scrollable و غير حساسة للتغيرات و انها CONCUR (متعددة الوصول) و لكنها للقراءة فقط .. راجع ResultSet

  4. connectedToDatabase عبارة عن متحول منطقي بولياني يحدد هل تم الأتصال بالقاعدة أو لا .. و يمكن ان تضع له أي اسم ... و في البداية تكون قيمته false أي أننا غير متصلين بالقاعدة بعد .
  5. statement.close(); connection.close(); مهمتها إغلاق العبارة و الوصلة .. و لا يمكن تنفيذ الاستعلامات بعد عملية الإغلاق ..
  6. setQuery هي إجراء مهمته تمرير الاستعلام للعبارة resultSet = statement.executeQuery( query ); و يمكن اختيار أي اسم نريده ... و كمة query ممكن أن نكتب أي اسم نريده .. بسرظ أن نستبدله في كل الأماكن ..

ملاحظات ..

  1. أخي الكريم ...ليس بالضرورة أن تأخذ الأمثلة بحرفيتها .. طالما المطلوب هو التعلم ... فأنت حاول الأتصال بقاعدة البيانات و تنفيذ استعلام و وضع النتيجة في الــ ResultSet ثم طباعتها للخرج باستخدام System.out.println ... لأن موضوع الــ Table Model يعتبر موضوع متقدم نوعا ما .. لكن لا بأس من تعلمه .. لكن في مرحلة متقدمة عندما تبدأ مع عناصر الــ GUI ..
  2. استخدم الــ Java Documentation للقراءة عن الصفوف ..رابط

شكراً لك أخي شرح وافي إن شاء الله ما شاء الله عليك

لكن أخي ذكرت إننا نستخدم Next للإنتقال إلى row آخر لكنه هنا مستخدم دالة last



resultSet.last();

فلماذا؟ و أنا جربت دالة next فقرأ أول صف فقط. و البديهي إننا نستخدم next لكن ماذا فكرته بإستخدام last ؟

بالنسبة connectedToDatabase أنا فهمت إننا ننشئها من عندنا ونعطيها قيمة بليوني لكي تساعدنا في كتابة شروط تخدمنا في أداء البرنامج و غير مرتبطة بأي مكتابات أو كلاسيس أو ميثود داخلية في جافا .

أخيراً لو أردت أن أغير بمدخلات الجدول قيمة خانة معينة أو تغير لونها ما الميثود الذي ينبغي أن أستخدمها جربت و غيرت لون الجدول كله لكن ما عرفت خانة وحدة.

هذا و بارك الله فيك و أتمنى أن لا أكون قد أطلت عليك .

مع الشكر

#8

السلام عليكم ...

  1. لو رجعنا إلى الــ java documentation الخاصة بــ ResultSet.getRow() رابط لوجدنا أنها تعيد رقم السطر الحالي ... (تذكر مشاركتي السابقة قلت أن الـ ResultSet فيها مؤشر للسطر الحالي) ..و بالتالي لمعرفة عدد الأسطر .. يتم نقل المؤشر إلى آخر سطر ثم أخذ رقم السطر الحالي الذي هو آخر سطر ...
  2. الــ Next تقوم بنقل المؤشر إلى السطر التالي ... و هذا مثال على طريقة استخدامها لقراءة كل السجلات في الــ ResultSet كمايلي :
    package ResultSet;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class ResultSetExample {
    
      public static void main(String[] args) {
    	Connection connection = null;
      	String url = "jdbc:mysql://localhost:3306/";
      	String dbName = "roseindia_jdbc_tutorials";
      	String driverName = "com.mysql.jdbc.Driver";
      	String userName = "root";
      	String password = "root";
      	try{
        	Class.forName(driverName).newInstance();
        	connection = DriverManager.getConnection(url+dbName, userName, password);
        	try{
          	Statement stmt = connection.createStatement();
          	String selectquery = "select * from user";
          	ResultSet rs = stmt.executeQuery(selectquery);
          	while(rs.next()){
            	System.out.print("User ID :" + rs.getInt(1)+ " ");
              	System.out.println("User Name :" + rs.getString(2));
          	}
        	}
        	catch(SQLException s){
          	System.out.println(s);
        	}
        	connection.close();
      	}
      	catch (Exception e){
        	e.printStackTrace();
      	}
      }
    }

    و المثال موجود في الرابط

  3. بالنسبة لــ connectedToDatabase فكلامك صحيح ..
  4. أما لتغيير لون خلية محددة فتحتاج إلى وراثة الصف DefaultTableCellRender و إليك الرابط (الجواب الصحيح في المشاركة الثانية)
1

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#9

شكراً لك أخي على مساعدتي :) لقد شرحت لي ما أحتاج بارك الله فيك

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…