Programming Basics SQL HTML CSS JavaScript Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Learn Typing

Javaالإنترفيس PreparedStatement في جافا

  • مقدمة
  • أهمية علامة الإستفهام ? عند إرسال إستعلامات
  • دوال الإنترفيس PreparedStatement
  • مثال شامل

مقدمة

الإنترفيس PreparedStatement يرث من الإنترفيس Statement, و أدائه أسرع منه أيضاً. تم تصميمه لإرسال إستعلامات إلى قاعدة البيانات أثناء عمل البرنامج, كما أنه يمكن إستخدامه لتنفيذ نفس أوامر الـ SQL عدة مرات.

للحصول على كائن PreparedStatement من كائن الـ Connection نستدعي الدالة prepareStatement().


بناؤه

public interface PreparedStatement
extends Wrapper, Statement, AutoCloseable
public interface PreparedStatement extends Wrapper, Statement, AutoCloseable

أهمية علامة الإستفهام ? عند إرسال إستعلامات

بما أن الإنترفيس PreparedStatement مصمم لإرسال إستعلامات أثناء تشغيل البرنامج, فهذا يعني أنه عليك:

  1. تجهيز شكل الإستعلام الأساسي الذي سيتم إرساله.
  2. جعل المستخدم يكمل نص الإستعلام.
  3. تنفيذ الإستعلام.

طريقة إستخدام علامة الإستفهام ? في نص الإستعلام

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


عند تجهيز نص الإستعلام الأساسي, نقوم بوضع علامة - أو علامات - الإستفهام فيه كالتالي.

مثال

PreparedStatement pstmt = con.prepareStatement("UPDATE employee SET name = ? WHERE id = ?");
PreparedStatement pstmt = con.prepareStatement("UPDATE employee SET name = ? WHERE id = ?");

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

مثال

pstmt.setString(1, "Ahmad"); // Ahmad مكان أول رمز ? سيتم وضع الإسم
pstmt.setInt(2, 12); // مكان ثاني رمز ? سيتم وضع الرقم 12
pstmt.setString(1, "Ahmad"); // Ahmad مكان أول رمز ? سيتم وضع الإسم pstmt.setInt(2, 12); // مكان ثاني رمز ? سيتم وضع الرقم 12

لاحقاً نستخدم دالة تنفيذ الإستعلام كالتالي.

مثال

pstmt.executeUpdate();
pstmt.executeUpdate();

إذاً هنا أصبح شكل نص الإستعلام الذي تم تنفيذه كالتالي: "UPDATE employee SET name = 'ahmad' WHERE id = 12".

إنتبه: علامات الإستفهام التي تضعها في نص الإستعلام, يتم ترقيمها إبتداءاً من الرقم 1 كما لاحظت في المثال السابق.



معلومة تقنية

عندما نكتب إستعلام و نضع فيه علامة إستفهام أو أكثر, يطلق على هذا الإستعلام تسمية Parameterized Query.
الدوال التي نستخدمها لتمرير القيم التي حصلنا عليها من المستخدم لوضعها مكان علامات الإستفهام, تسمى Setter Methods.

دوال الإنترفيس PreparedStatement

الجدول التالي يحتوي على أهم الدوال الموجودة في الإنترفيس PreparedStatement.

الدالة مع تعريفها
1 public void setInt(int parameterIndex, int value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه int يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع INTEGER.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
2 public void setLong(int parameterIndex, long value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه long يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع BIGINT.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
3 public void setFloat(int parameterIndex, float value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه float يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع REAL.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
4 public void setDouble(int parameterIndex, double value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه double يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع DOUBLE.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
5 public void setBoolean(int parameterIndex, boolean value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن قيمة نوعها boolean تحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع BIT أو BOOLEAN.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
6 public void setByte(int parameterIndex, byte value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه byte يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع TINYINT.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
7 public void setShort(int parameterIndex, short value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن رقم نوعه short يحدد القيمة التي سيتم وضعها مكان علامة السؤال الموضوعة في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع SMALLINT.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
8 public void setString(int parameterIndex, String value) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن نص يحدد القيمة التي سيتم وضعها مكان علامة السؤال في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر value إلى النوع VARCHAR أو LONGVARCHAR.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
9 public void setDate(int parameterIndex, Date date) نمرر لها قيمتين كـ Arguments, الأولى عبارة عن رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة, و الثانية عبارة عن كائن من الكلاس Date يحدد القيمة التي سيتم وضعها مكان علامة السؤال في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر date إلى النوع DATE.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
10 public void setCharacterStream(int parameterIndex, Reader reader, int length) تستخدم لتخزين ملف نصي في قاعدة البيانات عند إستدعائها نمرر لها ثلاثة قيم كـ Arguments كالتالي:
  1. مكان الباراميتر parameterIndex, نمرر رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة.
  2. مكان الباراميتر reader, نمرر كائن من الكلاس Reader يحدد إسم و رابط الملف الذي سيتم وضعه مكان علامة السؤال في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement.
  3. مكان الباراميتر length, نمرر رقم نوعه int يمثل عدد الأحرف التي يحتويها هذا الملف.

ملاحظة: الـ JDBC سيهتم بنوع الترميز المستخدم في هذا الملف بشكل تلقائي.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
11 public void setBinaryStream(int parameterIndex, InputStream is, int length) تستخدم لتخزين أي نوع من الملفات الغير نصية في قاعدة البيانات. عند إستدعائها نمرر لها ثلاثة قيم كـ Arguments كالتالي:
  1. مكان الباراميتر parameterIndex, نمرر رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة.
  2. مكان الباراميتر is, نمرر كائن من الكلاس InputStream يحدد إسم و رابط الصورة التي سيتم وضعها مكان علامة السؤال في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement.
  3. مكان الباراميتر length, نمرر رقم نوعه int يمثل حجم الملف بالـ Byte.

ملاحظة: الـ JDBC سيهتم بنوع الترميز المستخدم في هذا الملف بشكل تلقائي.

ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
12 public void setBlob(int parameterIndex, InputStream is, int length) تستخدم لتخزين صورة في قاعدة البيانات. عند إستدعائها نمرر لها ثلاثة قيم كـ Arguments كالتالي:
  1. مكان الباراميتر parameterIndex, نمرر رقم نوعه int يحدد index علامة السؤال التي سيتم تبديلها بقيمة.
  2. مكان الباراميتر is, نمرر كائن من الكلاس InputStream يحدد إسم و رابط الملف الذي سيتم وضعه مكان علامة السؤال في نص الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement.
  3. مكان الباراميتر length, نمرر رقم نوعه int يمثل حجم الملف بالـ Byte.

ملاحظة: الـ JDBC سيقوم بتحويل نوع القيمة التي تم وضعها مكان الباراميتر blob إلى النوع BLOB.

  • ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات.
  • ترمي الإستثناء SQLFeatureNotSupportedException في حال كان الـ JDBC لا يدعم هذه الدالة.
13 public ResultSet executeQuery() تنفذ الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.
ترجع نتيجة الإستعلام ككائن نوعه ResultSet.
الأمر الذي يمرر لها في العادة يكون أمر SELECT ثابت.

  • ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات, أو في حال لم يرجع الإستعلام كائن ResultSet.
  • ترمي الإستثناء SQLTimeoutException في حال بقي كائن الـ Statement في وضعية الإنتظار حتى تخطى المدة التي تم تحديدها بواسطة الدالة setQueryTimeout().
14 public int executeUpdate() تنفذ الإستعلام الذي تم تجهيزه في كائن الـ PreparedStatement الذي قام باستدعائها.
ترجع عدد الأسطر التي تم إضافتها أو التعديل عليها. و ترجع 0 في حال كان الإستعلام لا يرجع شيء.

  • ترمي الإستثناء SQLException في حال حدث خطأ عند محاولة الإتصال بقاعدة البيانات, أو في حال أرجع الإستعلام كائن ResultSet.
  • ترمي الإستثناء SQLTimeoutException في حال بقي كائن الـ Statement في وضعية الإنتظار حتى تخطى المدة التي تم تحديدها بواسطة الدالة setQueryTimeout().

مثال شامل

في المثال التالي سنفترض أننا سنقوم بالإتصال بقاعدة بيانات إسمها company تمثل قاعدة بيانات لشركة و مبنية بنظام MySQL.
يوجد في هذه القاعدة جدول خاص للموظفين إسمه employee.
في البداية سنجهز إستعلام الهدف منه تبديل إسم أي موظف نريد من الجدول.
بعدها, سنجعل البرنامج يطلب من المستخدم إدخال رقم الـ ID الخاص بهذا الموظف, ثم الإسم الجديد.
بعد إدخالهم, سيتم تحديث إسم الموظف في قاعدة البيانات.


Main.java
// هنا قمنا بإستدعاء الكلاسات و الإنترفيسات التي سنستخدمها للتعامل مع قاعدة البيانات
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
// لأننا سنطلب من المستخدم إدخال بيانات أثناء تشغيل البرنامج Scanner هنا قمنا بإستدعاء الكلاس
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// input إسمه Scanner هنا قمنا بإنشاء كائن من الكلاس
Scanner input = new Scanner(System.in);
try {
// الذي سنعتمد عليه للوصول إلى قاعدة البيانات MYSQL Driver هنا قمنا بتحديد رابط الوصول لبرنامج الـ
Class.forName("com.mysql.jdbc.Driver");
// و الذي سنستخدمه لتحديد المعلومات الأساسية التي نحتاجها للإتصال بقاعدة البيانات Connection هنا قمنا بإنشاء كائن من الكلاس
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/company","root","password");
// و الذي سنستخدمه لإرسال إستعلامات إلى قاعدة البيانات بناءاً على المعلومات التي يدخلها المستخدم PreparedStatement هنا قمنا بتجهيز كائن نوعه
PreparedStatement pstmt = con.prepareStatement("UPDATE employee SET name = ? WHERE id = ?");
// id الموظف الذي سيقوم بتغيير إسمه و وضعناه في المتغير ID هنا طلبنا من المستخدم إدخال
System.out.print("Select Employee, Enter his ID: ");
int id = input.nextInt();
// name هنا طلبنا من المستخدم إدخال الإسم الجديد و وضعناه في المتغير
System.out.print("Enter the new name: ");
String name = input.next();
// التي أدخلها المستخدم مكان أول علامة إستفهام موضوعة في الإستعلام name هنا قمنا بتمرير قيمة المتغير
pstmt.setString(1, name);
// التي أدخلها المستخدم مكان ثاني علامة إستفهام موضوعة في الإستعلام id هنا قمنا بتمرير قيمة المتغير
pstmt.setInt(2, id);
// هنا قمنا بتنفيذ الإستعلام
pstmt.executeUpdate();
// هنا قمنا بإغلاق الإتصال مع قاعدة البيانات
con.close();
}
catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
// هنا قمنا بإستدعاء الكلاسات و الإنترفيسات التي سنستخدمها للتعامل مع قاعدة البيانات import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; // لأننا سنطلب من المستخدم إدخال بيانات أثناء تشغيل البرنامج Scanner هنا قمنا بإستدعاء الكلاس import java.util.Scanner; public class Main { public static void main(String[] args) { // input إسمه Scanner هنا قمنا بإنشاء كائن من الكلاس Scanner input = new Scanner(System.in); try { // الذي سنعتمد عليه للوصول إلى قاعدة البيانات MYSQL Driver هنا قمنا بتحديد رابط الوصول لبرنامج الـ Class.forName("com.mysql.jdbc.Driver"); // و الذي سنستخدمه لتحديد المعلومات الأساسية التي نحتاجها للإتصال بقاعدة البيانات Connection هنا قمنا بإنشاء كائن من الكلاس Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/company","root","password"); // و الذي سنستخدمه لإرسال إستعلامات إلى قاعدة البيانات بناءاً على المعلومات التي يدخلها المستخدم PreparedStatement هنا قمنا بتجهيز كائن نوعه PreparedStatement pstmt = con.prepareStatement("UPDATE employee SET name = ? WHERE id = ?"); // id الموظف الذي سيقوم بتغيير إسمه و وضعناه في المتغير ID هنا طلبنا من المستخدم إدخال System.out.print("Select Employee, Enter his ID: "); int id = input.nextInt(); // name هنا طلبنا من المستخدم إدخال الإسم الجديد و وضعناه في المتغير System.out.print("Enter the new name: "); String name = input.next(); // التي أدخلها المستخدم مكان أول علامة إستفهام موضوعة في الإستعلام name هنا قمنا بتمرير قيمة المتغير pstmt.setString(1, name); // التي أدخلها المستخدم مكان ثاني علامة إستفهام موضوعة في الإستعلام id هنا قمنا بتمرير قيمة المتغير pstmt.setInt(2, id); // هنا قمنا بتنفيذ الإستعلام pstmt.executeUpdate(); // هنا قمنا بإغلاق الإتصال مع قاعدة البيانات con.close(); } catch(Exception e) { System.out.println(e.getMessage()); } } }

لو كانت قاعدة البيانات موجودة و قمنا بتشغيل البرنامج, سيطلب من المستخدم إدخال رقم ID الموظف الذي يريد تغيير إسمه, ثم الإسم الجديد الذي سيضعه مكانه.

قمنا بتعليم البيانات التي إنتظرنا البرنامج لإدخالها من لوحة المفاتيح باللون الأصفر.

Select Employee, Enter his ID: 1
Enter the new name: Ahmad