1. Сльози та біль

Під час роботи Java-програми можуть виникати помилки. Під час роботи з базою даних помилки будуть виникати. Вся справа лише в тому, які з них ти можеш передбачити та запропонувати адекватне рішення.

Перша велика група помилок на тебе чекатиме під час виконання цього рядка:

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

Що тут на тебе може очікувати?

Помилка 1. Драйвер не знайдено.

Якщо отримуєш помилку “No suitable driver found for …” це означає, що DriverManager не зміг зрозуміти, який тип СУБД ховається за твоїм URL. Наприклад, ти написав jdbc_mysql: замість jdbc:mysql:

Помилка 2. Помилка з'єднання.

Якщо ти припустився помилки в імені хоста, швидше за все, отримаєш повідомлення типу “No such host is known” або “Communications link failure”.

Помилка 3. Неправильно вказано ім'я бази даних.

Якщо ти припустився друкарської помилки в імені бази даних або підключаєшся до іншого сервера, де її немає, то отримаєш повідомлення типу “Unknown database 'supershop3'”.

Помилка 4. Неправильний логін або пароль.

Якщо ти забув пароль від бази або неправильно вказав його, швидше за все, отримаєш повідомлення типу “Access denied for user 'root'@'localhost' (using password: YES) ”.

2. SQL Exception

Якщо з'єднання з базою все ж таки встановилося, далі буде цікавіше. На випадок помилок під час роботи з базою у JDBC є спеціальний виняток — java.sql.SQLException. А також кілька його різновидів.

Цей виняток має лише один додатковий метод (у порівнянні з класом Exception) — це метод getSQLState(), який повертає код стану (рядок), який повернув йому SQL-сервер. Обробка помилок відбувається таким чином:


Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "secret");
try {
   int rowsCount = statement.executeUpdate("DELETE FROM ‘Unemployees’");
} catch (SQLException ex) {
  // Якщо таблиця не існує
   if (ex.getSQLState().compareTo("X0Y32") != 0) {
  throw ex;
  }
 } finally {
  connection.close();
 }

Кодів помилок при цьому кілька сотень. Повний список можеш дивитися тут.

Але іноді коди помилок допомагають JDBC зрозуміти помилку краще, і тоді він створює не просто SQLException, а спеціалізовані SQLException:

BatchUpdateException Помилка під час групового запиту
DataTruncation Часто виникає під час обрізання довгих даних
SQLClientInfoException Клієнт передав параметри, які не можуть бути встановлені у з'єднання: Connection
SQLDataException Помилка даних, деталі залежать від типу СУБД
SQLException Помилка доступу до бази або інші спільні помилки
SQLFeatureNotSupportedException СУБД не підтримує цю функціональність
SQLIntegrityConstraintViolationException Всі помилки з SQLState ==22
SQLInvalidAuthorizationSpecException Помилка доступу та/або авторизації
SQLNonTransientConnectionException Всі помилки з SQLState ==08
SQLRecoverableException Помилка є, але її можна виправити за допомогою application
SQLSyntaxErrorException Помилка синтаксису запиту
SQLTimeoutException Запит виконувався надто довго
SQLTransactionRollbackException Помилка під час відкату транзакції
SQLWarning Попередження, яке надіслала СУБД

3. Приклади помилок

Якщо помилка сталася на етапі роботи серверної програми, зазвичай її можна лише логувати і потім докладніше з нею розбиратися. А ось якщо вона сталася під час роботи програми на комп'ютері програміста, тут тобі потрібно ретельно дослідити причину.

Є два найбільші класи помилок під час роботи з базою даних:

  • Помилка тексту запиту
  • Помилка під час роботи з ResultSet

Помилка тексту запиту може виникати дуже часто. Запит може бути дуже довгим, містити кілька таблиць (об'єднаних через JOIN) та підзапитів (SUBSELECT). Знайти помилку в такому запиті непросто. Крім того, запити часто склеюються із частин, туди додаються дані.

Найперша помилка, про яку тобі слід знати, — це SQLSyntaxErrorException. Така помилка як правило означає, що в тебе є помилка в тілі запиту.

Візьмемо наш улюблений приклад:


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

І “випадково” зітремо зірочку в тілі запиту:


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

Тоді ми отримаємо виняток:

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

Ви маєте error in your SQL syntax; check the manual that corresponds to your MySQL server version for right syntax to used near ') FROM task' at line 1

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

SQL-сервер пише нам, що перед FROM була синтаксична помилка.

Уважно дивимося на запит і думаємо. Якщо нічого не спадає на думку, а таке буває дуже часто, потрібно попросити когось подивитися, що не так.

Ще одна популярна помилка — неправильна робота з ResultSet — результат запиту. Припустимо, ти забув, що перед читанням даних “поточний рядок” об'єкта ResultSet стоїть перед першим рядком. У цьому разі в тебе буде такий код:


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

Ти отримаєш таку помилку:


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)

Уважно дивимося на помилку та думаємо. Потім гуглимо і знаходимо кілька прикладів, і намагаємося зрозуміти рішення.