W3docs

Введение в Java JDBC

Что такое JDBC, как он абстрагирует доступ к базе данных в Java и архитектура JDBC API.

JDBC (Java Database Connectivity) — это стандартный API для взаимодействия с реляционной базой данных из Java. Он располагается в пакетах java.sql и javax.sql и предоставляет единый нейтральный к поставщику способ открыть соединение, отправить SQL и прочитать результаты — независимо от того, какая база данных используется: PostgreSQL, MySQL, Oracle, SQL Server или встраиваемая система вроде H2. Достаточно один раз изучить API, и при смене базы данных меняется только URL соединения.

Главная идея: тонкий унифицированный слой над множеством баз данных

Ваш код пишется против интерфейсовConnection, Statement, ResultSet. Конкретные классы, реализующие их, поставляются в JAR-файле драйвера от конкретного производителя. Задача JDBC — удерживать ваш код на стороне интерфейса этой границы, чтобы смена базы данных была изменением конфигурации, а не переписыванием кода.

Основные типы

Несколько интерфейсов встречается практически в каждой JDBC-программе:

ИнтерфейсРоль
DriverManagerНаходит драйвер для вашего URL и возвращает Connection
ConnectionАктивный сеанс с базой данных; фабрика для операторов
StatementОтправляет фиксированную SQL-строку
PreparedStatementОтправляет параметризованный SQL-шаблон (безопасный вариант по умолчанию)
CallableStatementВызывает хранимую процедуру
ResultSetКурсор по строкам, возвращённым запросом
SQLExceptionПроверяемое исключение, которое может выбросить любой JDBC-вызов

Структура любой JDBC-программы

Почти весь доступ к данным следует одним и тем же пяти шагам. Ниже приведён пример работы с реальной базой данных, где используется try-with-resources, чтобы каждый ресурс закрывался автоматически:

String url = "jdbc:postgresql://localhost:5432/shop";
String sql = "SELECT id, name FROM product WHERE price < ?";

try (Connection conn = DriverManager.getConnection(url, "app", "secret");
     PreparedStatement ps = conn.prepareStatement(sql)) {
  ps.setBigDecimal(1, new BigDecimal("9.99"));
  try (ResultSet rs = ps.executeQuery()) {
    while (rs.next()) {
      System.out.println(rs.getInt("id") + " " + rs.getString("name"));
    }
  }
}

А именно: (1) задайте базу данных через URL, (2) откройте Connection, (3) создайте оператор, (4) выполните его, (5) прочитайте ResultSet — затем закройте всё в обратном порядке. Остальная часть этого раздела раскрывает каждый шаг подробнее.

Нейтральная к поставщику система типов

Столбцы SQL — это не Java-типы. JDBC связывает их с помощью констант java.sql.TypesVARCHAR, INTEGER, TIMESTAMP и так далее — и параллельного набора методов getXxx/setXxx. Вам редко приходится сражаться с этим сопоставлением, однако именно поэтому столбец DATE при чтении превращается в java.sql.Date, а NUMERIC — в BigDecimal.

Рабочий пример: входная точка без установленного драйвера

Эта программа ни к чему не подключается — она исследует саму JDBC-машинерию. Она спрашивает DriverManager, какие драйверы зарегистрированы, демонстрирует точный контракт при отсутствии подходящего драйвера для URL и выводит несколько констант типов, на которых построен API.

java— editable, runs on the server

Что следует извлечь из запуска:

  • getConnection — единственная точка входа, опосредованная DriverManager. Вы никогда не создаёте соединение через new — вы называете базу данных через URL, а JDBC маршрутизирует запрос. В этом примере в среде выполнения нет зарегистрированных драйверов, поэтому счётчик равен 0.
  • Когда ни один драйвер не заявляет права на URL, JDBC не возвращает null и не зависает — он выбрасывает SQLException с сообщением 'No suitable driver found'. Все методы JDBC сигнализируют об ошибке именно так, поэтому SQLException является проверяемым и вы обрабатываете его повсюду.
  • Исключение содержало SQLState (08001, стандартный класс 'client unable to establish connection'). Коды SQLState переносимы между разными производителями, в отличие от целочисленных кодов ошибок, которые специфичны для конкретного поставщика.
  • Константы java.sql.Types — это обычные int (VARCHAR равен 12, INTEGER равен 4). Именно с их помощью API именует SQL-типы независимо от конкретной базы данных; вы будете передавать их в setNull и registerOutParameter в последующих главах.
  • Здесь не потребовалась база данных. JDBC API является частью JDK; только драйвер является внешним компонентом. В этом разделении и состоит весь замысел — ваш код компилируется и работает с типами java.sql без какой-либо базы данных в поле зрения.

Когда использовать JDBC

JDBC — это фундамент, на котором стоит каждый высокоуровневый инструмент для работы с данными в Java. Объектно-реляционные маперы вроде Hibernate или JPA, построители запросов вроде jOOQ и более лёгкие вспомогательные средства вроде Spring's JdbcTemplate — все они вызывают JDBC под капотом. Используйте JDBC напрямую, когда вам нужен полный контроль над SQL, минимальный объём зависимостей или когда вы изучаете, как этот слой работает на самом деле. Используйте ORM, когда предпочитаете сопоставлять строки с объектами и избегать шаблонного кода. В любом случае концепции этого раздела — соединения, операторы, результирующие наборы и транзакции — это именно то, чем управляют те инструменты за вас.

Что охватывает остаток этого раздела

Загрузка и выбор драйверов, открытие и настройка Connection, три вида операторов (Statement, PreparedStatement и CallableStatement), а также навигация по ResultSet, плюс транзакции, пакетные обновления и чтение метаданных базы данных. Следующая глава начинается там, где начинается каждое соединение: с драйвера.

Практика

Практика
В типичной JDBC-программе почему код приложения пишется против интерфейсов вроде Connection и ResultSet, а не против конкретных классов?
В типичной JDBC-программе почему код приложения пишется против интерфейсов вроде Connection и ResultSet, а не против конкретных классов?
Was this page helpful?