W3docs

Введение в Java JDBC

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

Введение в Java JDBC

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Активный сеанс с базой данных; фабрика для statements
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) создать statement, (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 в последующих главах.
  • Ничего из этого не требовало базы данных. API JDBC является частью JDK; внешним является только драйвер. Это разделение и есть весь замысел — ваш код компилируется и рассуждает о типах java.sql без какой-либо базы данных в поле зрения.

Что охватывает остаток этой части

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

Практика

Практика

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