JDBC-драйверы Java
Типы JDBC-драйверов, загрузка драйверов в современной Java и использование DriverManager и DataSource для получения соединений.
JDBC-драйвер — это библиотека, поставляемая производителем базы данных, которая преобразует обобщённые вызовы java.sql в конкретный сетевой протокол, понятный базе данных. JDBC API входит в состав JDK; драйвер — это внешний JAR-файл, который добавляется в classpath. Без драйвера нет соединения.
В этой главе рассматриваются четыре типа драйверов (и почему сегодня важен только один из них), способ автоматической загрузки драйверов в современной Java без Class.forName, разница между DriverManager и DataSource, а также то, как DriverManager определяет, какой драйвер обрабатывает данный URL. Для общего понимания того, как JDBC API устроен в целом, смотрите Java JDBC Introduction; чтобы начать работу с живым соединением после его получения, смотрите Java JDBC Connection.
Четыре типа драйверов
Спецификация JDBC определяет четыре исторических типа драйверов. На практике сегодня почти всегда используется тип 4:
| Тип | Название | Примечания |
|---|---|---|
| 1 | JDBC-ODBC bridge | Устарел; удалён из JDK в Java 8 |
| 2 | Native-API | Оборачивает C-клиентскую библиотеку; требует установки нативного кода |
| 3 | Network protocol | Взаимодействует с промежуточным слоем, который обращается к базе данных |
| 4 | Pure-Java (thin) | Один JAR, полностью на Java, напрямую говорит по wire-протоколу БД |
Драйверы типа 4 — org.postgresql.Driver, com.mysql.cj.jdbc.Driver, драйвер H2 — это просто JAR в classpath. Именно они добавляются в pom.xml или build.gradle. Поскольку они написаны на чистом Java, они работают на любой платформе, поддерживаемой JVM, без необходимости устанавливать что-либо на хост-машине. Относитесь к старым типам как к историческим: вы встретите их в старой документации и на экзаменах, но в новом коде к ним не прибегают.
Загрузка драйвера: обычно ничего делать не нужно
Старые руководства показывают Class.forName("com.mysql.cj.jdbc.Driver"). Начиная с JDBC 4.0 (Java 6) эта строка не нужна. Драйверы поставляются с файлом META-INF/services/java.sql.Driver, и DriverManager автоматически регистрирует их через механизм ServiceLoader при первом вызове getConnection. Поэтому современный код выглядит просто:
// No Class.forName needed — the driver JAR self-registers.
Connection conn = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/shop", "app", "secret");DriverManager и DataSource
Два способа получить соединение:
DriverManager.getConnection(url, user, password)— простейший вариант; подходит для инструментов, скриптов и демонстраций. При каждом вызове открывает новое физическое соединение.DataSource— предпочтительный подход для приложений и серверов.DataSource(обычно реализованный через пул соединений, например HikariCP) выдаёт пулируемые соединения, поэтомуclose()возвращает соединение в пул, а не закрывает сокет.
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/shop");
ds.setUsername("app");
ds.setPassword("secret");
try (Connection conn = ds.getConnection()) { /* borrowed from the pool */ }JDBC URL
Каждое соединение начинается с JDBC URL, который всегда имеет вид jdbc:<subprotocol>:<subname>:
jdbc:postgresql://localhost:5432/shop
│ │ │
│ │ └─ subname: host, port, database, options
│ └───────────── subprotocol: identifies the vendor/driver
└────────────────── scheme: always "jdbc"Subprotocol (postgresql, mysql, h2, oracle, sqlserver) — это часть, определяющая, какой драйвер обрабатывает запрос. Каждый производитель документирует собственный формат URL и параметры, следующие за именем базы данных (настройки TLS, часовой пояс, флаги соединения), поэтому обращайтесь к документации драйвера для уточнения точного синтаксиса.
Как DriverManager выбирает драйвер
При вызове getConnection DriverManager перебирает список зарегистрированных драйверов и спрашивает каждый из них: «Вы распознаёте этот URL?» — через Driver.acceptsURL. Первый, ответивший «да», используется; если ни один не ответил, выбрасывается No suitable driver found. Как правило, драйвер отвечает «да» только тогда, когда subprotocol URL совпадает с его собственным — именно поэтому маршрутизацию запроса определяет subprotocol, а не хост.
Практический пример: инспекция реестра драйверов
Эта программа выводит список драйверов, известных DriverManager, а затем просит его подключиться к трём URL разных производителей — позволяя наблюдать за механизмом сопоставления URL в действии.
Что следует вынести из запуска:
DriverManager.getDrivers()возвращает зарегистрированные драйверы в видеEnumeration. На рантайме без JAR-файлов драйверов список пуст — добавьтеpostgresql.jarв classpath, и PostgreSQLDriverпоявится здесь автоматически, без вызоваClass.forName.- Subprotocol URL (часть после
jdbc:—postgresql,mysql,h2) — это то, по чему каждый драйвер выполняет сопоставление. Именно так один вызовgetConnectionнаправляется к нужному производителю: драйвер заявляет права на свой subprotocol. - Каждый URL завершился ошибкой одинаково, потому что ни один драйвер не присутствовал. В реальном развёртывании ровно один драйвер заявит права на каждый URL; если вы забудете зависимость, вы получите именно это сообщение «No suitable driver found» — симптом отсутствия JAR, а не неверного пароля.
- Регистрация происходит автоматически через
ServiceLoader, но JAR-файл драйвера всё равно должен быть в classpath. Вывод: ошибка «No suitable driver» — это проблема сборки/зависимостей, которая решается вpom.xml, а не в коде Java. DriverпредоставляетgetMajorVersion/getMinorVersion, что позволяет логировать точную версию используемого драйвера — полезно, когда ошибка зависит от версии драйвера, а не от вашего кода.
Как только драйвер оказывается в classpath и getConnection возвращает живое Connection, следующим шагом является выполнение SQL через него — смотрите Java JDBC Connection и Java JDBC Statement.