Air mata dan kesakitan

Ralat mungkin berlaku semasa menjalankan program Java. Apabila bekerja dengan pangkalan data, ralat akan berlaku. Ini semua tentang yang mana antara mereka boleh anda ramalkan dan tawarkan penyelesaian yang mencukupi.

Kumpulan besar ralat pertama akan menunggu anda apabila melaksanakan baris ini:

Connection connection  = DriverManager.getConnection("jdbc:mysql://localhost:3306/test",  "root", "secret");

Apa yang boleh anda harapkan di sini?

Ralat 1. Pemandu tidak ditemui .

Jika anda mendapat ralat "Tiada pemacu yang sesuai ditemui untuk ..." , ini bermakna DriverManager tidak dapat memahami jenis DBMS di sebalik URL anda. Sebagai contoh, anda menulis jdbc_mysql: bukannya jdbc:mysql:

Ralat 2. Ralat sambungan .

Jika anda membuat kesilapan dalam nama hos, kemungkinan besar anda akan mendapat mesej seperti "Tiada hos sedemikian diketahui" atau "Kegagalan pautan komunikasi".

Ralat 3. Nama pangkalan data tidak betul .

Jika anda salah mengeja nama pangkalan data atau menyambung ke pelayan lain yang tidak wujud, anda akan mendapat mesej seperti “Pangkalan data tidak diketahui 'supershop3'” .

Ralat 4. Log masuk atau kata laluan salah .

Jika anda terlupa kata laluan pangkalan data atau memasukkannya secara salah, kemungkinan besar anda akan menerima mesej seperti “Akses ditolak untuk pengguna 'root'@'localhost' (menggunakan kata laluan: YES)” .

Pengecualian SQL

Sekiranya sambungan ke pangkalan itu tetap ditubuhkan, maka ia akan menjadi lebih menarik lagi. Sekiranya berlaku ralat semasa bekerja dengan pangkalan data, JDBC mempunyai pengecualian khas - java.sql.SQLException . Serta beberapa jenisnya.

Pengecualian ini hanya mempunyai satu kaedah tambahan (berbanding dengan kelas Pengecualian) - kaedah getSQLState(), yang mengembalikan kod status (rentetan) yang pelayan SQL kembalikan kepadanya. Pengendalian ralat kelihatan seperti ini:

Connection connection  = DriverManager.getConnection("jdbc:mysql://localhost:3306/test",  "root", "secret");
try {
   int rowsCount = statement.executeUpdate("DELETE FROM ‘Unemployees’");
} catch (SQLException ex) {
  // If table doesn't exist
   if (ex.getSQLState().compareTo("X0Y32") != 0) {
  	throw ex;
  }
 } finally {
  connection.close();
 }

Terdapat ratusan kod ralat. Anda boleh melihat senarai penuh di sini .

Tetapi kadangkala kod ralat membantu JDBC memahami ralat dengan lebih baik dan kemudian ia tidak hanya membuang SQLException, tetapi SQLException khusus:

BatchUpdateException Ralat semasa permintaan kumpulan
DataTruncation Selalunya berlaku apabila memotong data yang panjang
SQLClientInfoException Pelanggan meluluskan parameter yang tidak boleh ditetapkan pada sambungan: Sambungan
SQLDataException Ralat dengan data, butiran bergantung pada jenis DBMS
SQLException Ralat capaian pangkalan data atau ralat umum lain
SQLFeatureNotSupportedException DBMS tidak menyokong fungsi ini
SQLIntegrityConstraintViolationException Semua ralat dengan untuk SQLState ==22
SQLInvalidAuthorizationSpecException Ralat akses dan/atau kebenaran
SQLNonTransientConnectionException Semua ralat dengan untuk SQLState ==08
SQLRecoverableException Terdapat ralat, tetapi ia boleh diperbaiki dengan campur tangan aplikasi
SQLSyntaxErrorException Ralat dalam sintaks pertanyaan
SQLTimeoutException Permintaan mengambil masa terlalu lama
SQLTransactionRollbackException Ralat semasa rollback transaksi
SQLWarning Amaran yang dikeluarkan oleh DBMS

Contoh ralat

Jika ralat berlaku pada peringkat aplikasi pelayan, maka biasanya ia hanya boleh dilog dan kemudian ditangani dengan lebih terperinci. Tetapi jika ia berlaku semasa aplikasi berjalan pada komputer pengaturcara, maka anda perlu menyiasat dengan teliti sebabnya.

Terdapat dua kelas ralat terbesar apabila bekerja dengan pangkalan data:

  • Ralat teks permintaan
  • Ralat semasa bekerja dengan ResultSet

Ralat dalam teks permintaan boleh berlaku sangat kerap. Pertanyaan boleh menjadi sangat panjang, mengandungi beberapa jadual (digabungkan melalui JOIN) dan subqueries (SUBSELECT). Bukan mudah untuk mencari ralat dalam permintaan sedemikian. Di samping itu, permintaan sering dilekatkan bersama dari bahagian, data ditambah di sana.

Ralat pertama yang perlu anda ketahui ialah SQLSyntaxErrorException . Ralat sedemikian biasanya bermakna anda mempunyai kesilapan menaip dalam badan permintaan.

Mari kita ambil contoh kegemaran kita:

ResultSet results = statement.executeQuery("SELECT Count(*) FROM user");
results.next();
    int count = results.getInt(1);

Dan "secara tidak sengaja" memadamkan asterisk dalam badan permintaan:

ResultSet results = statement.executeQuery("SELECT Count() FROM user");
results.next();
    int count = results.getInt(1);

Kemudian kita akan mendapat pengecualian:

Exception in thread "main" java.sql.SQLSyntaxErrorException:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') FROM task' at line 1

           	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)

Pelayan SQL memberitahu kami bahawa terdapat ralat sintaks sebelum FROM.

Kami melihat dengan teliti permintaan dan berfikir. Jika tiada apa-apa yang terlintas dalam fikiran, dan ini berlaku sangat kerap, maka anda perlu meminta seseorang untuk melihat apa yang salah.

Satu lagi kesilapan popular ialah kerja yang tidak betul dengan ResultSet - hasil permintaan. Katakan anda terlupa bahawa sebelum membaca data, "baris semasa" objek ResultSet datang sebelum baris pertama, maka anda akan mempunyai kod berikut:

ResultSet results = statement.executeQuery("SELECT Count(*) FROM user");
//    results.next();
    int count = results.getInt(1);

Anda akan mendapat ralat ini:


2012 12:55:48 AM jButton5ActionPerformed
SEVERE: null
java.sql.SQLException: Before start of result set
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
    at com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
    at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5650)
    at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5570)

Kami dengan teliti melihat kesilapan dan berfikir. Kemudian kita google dan cari beberapa contoh dan cuba memahami penyelesaiannya.