W3docs

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:

ТипНазваниеПримечания
1JDBC-ODBC bridgeУстарел; удалён из JDK в Java 8
2Native-APIОборачивает C-клиентскую библиотеку; требует установки нативного кода
3Network protocolВзаимодействует с промежуточным слоем, который обращается к базе данных
4Pure-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 в действии.

java— editable, runs on the server

Что следует вынести из запуска:

  • DriverManager.getDrivers() возвращает зарегистрированные драйверы в виде Enumeration. На рантайме без JAR-файлов драйверов список пуст — добавьте postgresql.jar в classpath, и PostgreSQL Driver появится здесь автоматически, без вызова 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.

Практика

Практика
Современное приложение вашего коллеги (Java 17) выбрасывает 'No suitable driver found for jdbc:postgresql://...' при запуске. Каково наиболее вероятное решение?
Современное приложение вашего коллеги (Java 17) выбрасывает 'No suitable driver found for jdbc:postgresql://...' при запуске. Каково наиболее вероятное решение?
Was this page helpful?