أساسيات JDBC
الاتصالات والعبارات ومجموعات النتائج
أساسيات JDBC درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
ما هو JDBC؟
إن JDBC (Java Database Connectivity) هو واجهة API القياسية للتعامل مع قواعد البيانات العلائقية من Java.
- يوجد ضمن الحزمة
java.sql. - توفّر كل قاعدة بيانات برنامج تشغيل يطبّق واجهات JDBC.
- تكتبون الشيفرة باستخدام واجهات مثل
ConnectionوStatementوResultSet، ولا تتعاملون مباشرةً مع أصناف المورّد.
تتيح هذه الطبقة التجريدية للشيفرة نفسها العمل مع PostgreSQL أو MySQL أو H2 أو Oracle.
الواجهات الأساسية
تتولى ثلاث واجهات معظم العمل:
Connection— جلسة مفتوحة مع قاعدة البيانات.Statement/PreparedStatement— يرسل SQL.ResultSet— مؤشر يتنقل بين الصفوف التي يعيدها الاستعلام.
تحصلون على Connection من DriverManager أو DataSource.
فتح اتصال
تعيد DriverManager.getConnection(url, user, password) كائناً حياً من نوع Connection.
يحدد عنوان JDBC قاعدة البيانات، مثل jdbc:postgresql://localhost:5432/shop. وتسجّل برامج التشغيل الحديثة نفسها تلقائياً، لذلك لم تعودوا بحاجة إلى استدعاء Class.forName(...).
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
System.out.println("Connected: " + !conn.isClosed());
} catch (SQLException e) {
System.out.println("Connection failed: " + e.getMessage());
}
}
}try-with-resources
تطبّق كل من Connection وStatement وResultSet الواجهة AutoCloseable.
افتحوها دائماً داخل كتلة try-with-resources حتى تُغلَق تلقائياً، حتى عند طرح استثناء. إذ إن تسرّب الاتصالات يستنفد موارد قاعدة البيانات بسرعة.
- تُغلَق الموارد بترتيب عكسي.
- لا حاجة إلى كتلة
finally.
تنفيذ استعلام
لتنفيذ SELECT بسيط، أنشئوا كائناً من نوع Statement واستدعوا executeQuery، الذي يعيد كائناً من نوع ResultSet.
يستخدم المثال محاكاة داخل الذاكرة حتى تتمكنوا من رؤية سير العملية دون قاعدة بيانات حقيقية. وفي بيئة الإنتاج، ستُنفَّذ SQL على الاتصال.
import java.util.List;
public class Main {
public static void main(String[] args) {
// Simulated result of: SELECT name FROM users
List<String> names = List.of("Ada", "Linus", "Grace");
System.out.println("Query returned " + names.size() + " rows:");
for (String name : names) {
System.out.println(" - " + name);
}
}
}قراءة ResultSet
يبدأ ResultSet قبل الصف الأول. استدعوا rs.next() داخل حلقة؛ إذ تعيد false عند عدم وجود صفوف أخرى.
اقرؤوا الأعمدة باستخدام الاسم أو الفهرس الذي يبدأ من 1، مع أدوات الحصول ذات النوع المحدد:
rs.getInt("id")rs.getString("name")rs.getDouble("price")
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT id, name FROM users")) {
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}استخدام executeUpdate للكتابة
استخدموا executeUpdate مع INSERT وUPDATE وDELETE. إذ تعيد قيمة من النوع int تمثل عدد الصفوف المتأثرة.
استخدموا execute فقط عندما لا تعرفون مسبقاً ما إذا كانت العبارة ستعيد مجموعة نتائج.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement()) {
int rows = st.executeUpdate("DELETE FROM sessions WHERE expired = true");
System.out.println("Deleted " + rows + " rows");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}تحويل الصفوف إلى كائنات
تحوّل معظم التطبيقات كل صف إلى كائن من كائنات المجال. كرروا على ResultSet وأنشئوا النسخ اللازمة.
إليكم النمط المتبع، وقد جرت محاكاته بحيث يعمل بشكل مستقل. ويجعل record عملية التحويل موجزة.
import java.util.ArrayList;
import java.util.List;
public class Main {
record User(int id, String name) {}
public static void main(String[] args) {
// Stand-in for iterating a ResultSet
String[][] rows = {{"1", "Ada"}, {"2", "Linus"}};
List<User> users = new ArrayList<>();
for (String[] row : rows) {
users.add(new User(Integer.parseInt(row[0]), row[1]));
}
users.forEach(System.out::println);
}
}معالجة SQLException
تطرح كل طرق JDBC تقريباً الاستثناء المفحوص SQLException.
ويحمل هذا الاستثناء معلومات تشخيصية مفيدة:
getMessage()— نص قابل للقراءة البشرية.getSQLState()— رمز الحالة القياسي المكوّن من 5 محارف.getErrorCode()— الرمز الخاص بالمورّد.
سجّلوا هذه المعلومات بدلاً من تجاهل الاستثناءات.
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
SQLException e = new SQLException("duplicate key", "23505", 7);
System.out.println("Message: " + e.getMessage());
System.out.println("SQLState: " + e.getSQLState());
System.out.println("ErrorCode: " + e.getErrorCode());
}
}DatabaseMetaData
تعيد conn.getMetaData() كائناً من نوع DatabaseMetaData يصف قاعدة البيانات نفسها.
ويمكنه إخباركم باسم المنتج وإصداره والميزات المدعومة، بل وسرد الجداول والأعمدة أيضاً. هكذا تعمل أدوات مثل متصفحات المخطط دون تضمين تفاصيل المورّد في الشيفرة بشكل ثابت.
جمع العناصر معاً
يتبع تدفق القراءة المعتاد الخطوات التالية:
- افتحوا
Connectionداخل try-with-resources. - أنشئوا
Statement(أو، وهو الأفضل،PreparedStatement). - استدعوا
executeQueryوكرروا باستخدامrs.next(). - حوّلوا الأعمدة إلى كائنات.
- اتركوا try-with-resources يغلق كل شيء.
في الدرس التالي سنجعل الاستعلامات آمنة ضد حقن SQL.
تحقق سريع
ماذا تعيد Statement.executeUpdate؟
مراجعة
أصبحتم الآن تعرفون التدفق الأساسي لـ JDBC:
- تفتح
DriverManager.getConnectionكائناً من نوعConnection. - ترسل
Statementأوامر SQL؛ ويعيدexecuteQueryكائناً من نوعResultSet، بينما يعيدexecuteUpdateعدد الصفوف المتأثرة. - كرروا باستخدام
rs.next()وأدوات الحصول ذات النوع المحدد. - استخدموا دائماً try-with-resources، وعالجوا
SQLExceptionمع رموز الحالة والخطأ الخاصة به.
الأسئلة الشائعة
هل درس «أساسيات JDBC» مجاني؟
نعم — نص درس «أساسيات JDBC» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات JDBC»؟
الاتصالات والعبارات ومجموعات النتائج تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات JDBC»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.