Как использовать базу данных MySQL в Java

Обложка: Как использовать базу данных MySQL в Java

В этой статье мы научимся подключаться к базе данных MySQL из Java-кода и выполнять простые запросы для получения и обновления данных. Для того, чтобы получить доступ к базе данных, мы будем использовать JDBC (Java Database Connectivity) API, который входит в стандартную библиотеку Java. JDBC позволяет подключиться к любой базе данных: Postgres, MySQL, SQL Server, Oracle и т. д. — при наличии соответствующей реализации драйвера, необходимого для подключения. Для базы данных MySQL мы будем использовать драйвер Type 4 JDBC из пакета mysql-connector-java-5.1.23-bin.jar. Он написан на чистой Java, а значит, нам не понадобятся какие-либо нативные библиотеки или ODBC-мост. Все, что нам надо будет сделать — это положить JAR-файл в директорию, содержащуюся в CLASSPATH. JAR-файл содержит класс com.mysql.jdbc.Driver, необходимый для подключения к MySQL. Если его не окажется в CLASSPATH, во время выполнения программы выбросится исключение java.lang.ClassNotFoundException, поэтому убедитесь, что вы правильно настроили пути.

Ключевые выводы:
— JDBC API позволяет подключаться к MySQL из Java через стандартную библиотеку без сторонних фреймворков
— Для подключения достаточно драйвера mysql-connector-java в CLASSPATH и строки соединения jdbc:mysql://host:port/db
— Всегда закрывайте Connection, Statement и ResultSet в finally-блоке или используйте try-with-resources
— Для чтения данных используйте executeQuery(), для записи — executeUpdate()
— В боевом коде заменяйте Statement на PreparedStatement для защиты от SQL-инъекций

Кстати, если вы ищете хорошую книгу по использованию JDBC, обратите внимание на Practical Database Programming with Java (Ying Bai). Это относительно новая книга, и в ней рассматриваются две самые популярные базы данных: Oracle и SQL Server 2008. В книге используется IDE NetBeans для примеров и описываются все инструменты, необходимые для работы с базами данных в Java. Это отличная книга для начинающих и опытных программистов.

Подключаем базу данных MySQL с помощью JDBC

Для того, чтобы подключить базу данных MySQL, нам потребуется четыре вещи:

  1. Строка подключения JDBC (например:
    jdbc:mysql://localhost:3306/test).
  2. Имя пользователя (root).
  3. Пароль (root).
  4. База данных с некоторым количеством таблиц для примера (например, база данных книг).

Строка подключения для MySQL начинается с jdbc:mysql. Это название протокола соединения, за которым следуют хост и порт подключения, на которых запущена база данных. В нашем случае это localhost с портом по умолчанию 3306 (если вы его не поменяли при установке). Следующая часть — test — имя базы данных, которая уже существует в MySQL. Мы можем создать таблицу Books:

			CREATE TABLE `books` (
  `id` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  `author` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
		

и наполнить её хорошими книгами:

			INSERT INTO test.books (id, `name`, author)
    VALUES (1, 'Effective Java', 'Joshua Bloch');
INSERT INTO test.books (id, `name`, author)
    VALUES (2, 'Java Concurrency in Practice', 'Brian Goetz');
		

Программа на Java для работы с базой данных

Теперь давайте напишем программу на Java, которая будет подключаться к нашей базе данных, запущенной на localhost. Важно помнить о том, что необходимо закрывать соединение, запросы и результат выполнения после завершения работы с ними. Также важно закрывать их в finally-блоке, со своей try/catch оберткой, поскольку сам метод close() может кинуть исключение, что приведет к утечке ресурсов. За подробной информацией вы можете обратиться к этой статье. Кроме того, вы можете использовать обертку try-with-resource, которая появилась в Java 7. Более того, это стандартный способ работы с ресурсами в Java 1.7.

			import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Simple Java program to connect to MySQL database running on localhost and
 * running SELECT and INSERT query to retrieve and add data.
 * @author Javin Paul
 */
public class JavaToMySQL {

    // JDBC URL, username and password of MySQL server
    private static final String url = "jdbc:mysql://localhost:3306/test";
    private static final String user = "root";
    private static final String password = "root";

    // JDBC variables for opening and managing connection
    private static Connection con;
    private static Statement stmt;
    private static ResultSet rs;

    public static void main(String args[]) {
        String query = "select count(*) from books";

        try {
            // opening database connection to MySQL server
            con = DriverManager.getConnection(url, user, password);

            // getting Statement object to execute query
            stmt = con.createStatement();

            // executing SELECT query
            rs = stmt.executeQuery(query);

            while (rs.next()) {
                int count = rs.getInt(1);
                System.out.println("Total number of books in the table : " + count);
            }

        } catch (SQLException sqlEx) {
            sqlEx.printStackTrace();
        } finally {
            //close connection ,stmt and resultset here
            try { con.close(); } catch(SQLException se) { /*can't do anything */ }
            try { stmt.close(); } catch(SQLException se) { /*can't do anything */ }
            try { rs.close(); } catch(SQLException se) { /*can't do anything */ }
        }
    }

}
		

При первом запуске у вас, возможно, будет ошибка No suitable driver found for jdbc:mysql, если драйвера MySQL нет в CLASSPATH:

			java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test/book
    at java.sql.DriverManager.getConnection(DriverManager.java:689)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at JavaToMySQL.main(JavaToMySQL.java:29)
Exception in thread "main" java.lang.NullPointerException
    at JavaToMySQL.main(JavaToMySQL.java:46)
Java Result: 1
		

Добавим нужный JAR-файл в путь и снова запустим программу. Другая частая ошибка — указать таблицу в строке соединения: jdbc:mysql://localhost:3306/test/book. В этом случае вылетит следущее исключение:

			com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'test/book'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance
(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance
(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
		

Успешный запуск программы выведет на экран следующее:

			Total number of books in the table: 2
		

Результат верный, поскольку у нас в таблице только две книги: Effective Java и Java Concurrency in Practice.

Кстати, если у вас был драйвер при компиляции, но отсутствует при запуске, вы получите исключение java.lang.ClassNotFoundException: com.mysql.jdbc.Driver. О том, как исправить эту ошибку, вы можете прочитать здесь.

Получаем данные с помощью SELECT-запроса в JDBC

Для получения данных из БД вы можете выполнить SELECT-запрос. В первом примере мы уже его использовали, но получили только количество строк. Теперь мы вернем сами строки. Большая часть программы останется без изменений, за исключением SQL-запроса и кода, возвращающего данные из объекта ResultSet:

			String query = "select id, name, author from books";

rs = stmt.executeQuery(query);

while (rs.next()) {
   int id = rs.getInt(1);
   String name = rs.getString(2);
   String author = rs.getString(3);
   System.out.printf("id: %d, name: %s, author: %s %n", id, name, author);
 }
		

Этот код выведет на экран следующее:

			id: 1, name: Effective Java, author: Joshua Bloch
id: 2, name: Java Concurrency in Practice, author: Brian Goetz
		

Тут есть пара моментов, на которые следует обратить внимание. Метод rs.getInt(1) используется для получения столбца с целочисленным типом, в нашем случае это столбец id. Индексы в JDBC начинаются с единицы, поэтому rs.getInt(1) вернет значение первого столбца как целое число. В случае, если вы укажете неверный индекс (многие разработчики вызывают rs.getInt(0) для получения первого столбца), выбросится исключение InvalidColumnIndexException. Доступ к столбцам по индексу чреват ошибками, поэтому лучше использовать имя столбца, например, rs.getInt("id"). Подробнее об этом вы можете прочитать в этой статье. Метод getString() используется для получения строковых значений из базы (например, VARCHAR). Цикл будет выполняться, пока rs.next() не вернет false. Это значит, что строки закончились. В нашем случае в таблице две строки, поэтому цикл выполнится два раза, выводя информацию о книгах из таблицы на экран.

Добавляем данные с помощью INSERT-запроса в JDBC

Добавление данных мало отличается от их получения: мы просто используем INSERT-запрос вместо SELECT-запроса и метод executeUpdate() вместо executeQuery(). Этот метод используется для запросов INSERT, UPDATE и DELETE, а также для SQL DDL выражений, таких как CREATE, ALTER или DROP. Эти команды не возвращают результата, поэтому мы убираем все упоминания ResultSet'а в коде и изменяем запрос соответственно:

			String query = "INSERT INTO test.books (id, name, author) \n" +
               " VALUES (3, 'Head First Java', 'Kathy Sieara');";

// executing SELECT query
stmt.executeUpdate(query);
		

После запуска программы вы можете проверить таблицу в СУБД. На этот раз вы увидите три записи в таблице:

Теперь вы умеете подключаться к MySQL из Java-приложения и выполнять SELECT, INSERT, DELETE и UPDATE-запросы так же, как и в MySQL GUI. Для подключения мы используем объект Connection, для чтения результатов запроса — ResultSet. Убедитесь перед подключением, что сервер MySQL запущен и mysql-connector-java-5.1.17-bin.jar находится в CLASSPATH, чтобы избежать ClassNotFoundException.

Когда разберетесь с подключением и простыми запросами, имеет смысл изучить, как использовать подготавливаемые запросы (Prepared Statement) в Java для избежания SQL-инъекции. В боевом коде всегда следует использовать подготавливаемые запросы и связывание переменных.

Если вам понравилось это руководство и не терпится узнать больше о подключении и работе с базой данных из Java-программ, обратите внимание на следующие статьи:

  • Если у вас нет базы данных MySQL, вы можете ее скачать здесь;
  • Если у вас нет драйвера MySQL для JDBC, вы можете скачать его отсюда;
  • Рекомендованную книгу Practical Database Programming with Java можно купить на Amazon.

Часто задаваемые вопросы

Какой JDBC-драйвер нужен для MySQL?
Для подключения к MySQL из Java используется драйвер mysql-connector-java (MySQL Connector/J). Это драйвер Type 4, написанный на чистой Java. Скачайте JAR-файл с официального сайта MySQL и добавьте его в CLASSPATH вашего проекта. Если вы используете Maven, добавьте зависимость mysql:mysql-connector-java в pom.xml.
Как исправить ошибку No suitable driver found?
Эта ошибка означает, что JDBC-драйвер MySQL не найден в CLASSPATH. Убедитесь, что JAR-файл mysql-connector-java добавлен в путь к классам. Также проверьте строку подключения — она должна начинаться с jdbc:mysql:// и не содержать имени таблицы (только хост, порт и имя базы данных).
Чем отличается Statement от PreparedStatement?
Statement выполняет статические SQL-запросы, а PreparedStatement поддерживает параметризованные запросы с подстановкой значений через placeholder-ы (?). PreparedStatement защищает от SQL-инъекций, работает быстрее при повторных вызовах и автоматически экранирует специальные символы. В боевом коде всегда используйте PreparedStatement.
Нужно ли закрывать Connection, Statement и ResultSet?
Да, обязательно. Незакрытые ресурсы приводят к утечке соединений и памяти. Закрывайте их в finally-блоке в порядке ResultSet, Statement, Connection. В Java 7 и выше используйте try-with-resources — ресурсы закроются автоматически при выходе из блока.

Перевод статьи How to Connect to MySQL database in Java with Example