JDBC
JDBC — стандартный Java API для работы с реляционной БД через драйвер. Он задаёт интерфейсы, а драйвер конкретной СУБД реализует сетевой протокол и преобразование типов.
Основные объекты
DataSource— источник соединений; в приложении обычно связан с пулом;Connection— сессия с БД и граница транзакции;PreparedStatement— подготовленная параметризованная команда;ResultSet— курсор результата;SQLException— ошибка с SQL state и кодом поставщика.
String sql = "select id, name from customer where status = ?";
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, status);
try (ResultSet rows = statement.executeQuery()) {
while (rows.next()) {
long id = rows.getLong("id");
String name = rows.getString("name");
}
}
}Параметры нельзя применять к именам таблиц, столбцов или ключевым словам. Такие динамические части выбирают из белого списка, а значения передают через ?.
Транзакция
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try {
// несколько команд на одном connection
connection.commit();
} catch (Exception exception) {
connection.rollback();
throw exception;
}
}Возврат соединения в пул не равен физическому закрытию, но close() обязателен: он освобождает ресурс и позволяет пулу сбросить состояние.
Batch
addBatch и executeBatch уменьшают число сетевых обменов. Эффект зависит от драйвера и его настроек. Большой batch следует делить на части, учитывать размер транзакции и анализировать частичный успех через BatchUpdateException.
Типичные сбои
- утечка
Connection,StatementилиResultSet; - SQL injection из-за конкатенации;
- N+1 на уровне сетевых вызовов;
- длинная транзакция удерживает соединение и блокировки;
- неверное чтение
NULL: для примитивного getter нуженwasNull()либо объектный тип; - пул исчерпан не потому, что «мало соединений», а из-за медленных запросов или утечек.
Вопросы для повторения
StatementиPreparedStatementотличаются только скоростью? Нет, параметрыPreparedStatementотделяют данные от SQL и защищают значения от injection.- Почему нужен пул? Создание сетевого соединения дорого; пул повторно использует ограниченное число соединений.
- Потокобезопасен ли
Connection? На совместное использование между потоками рассчитывать нельзя. - Что делает auto-commit? Фиксирует каждую завершённую команду как отдельную транзакцию.
- Когда JDBC лучше ORM? Когда нужен точный SQL, streaming, batch или массовая операция без графа сущностей.
Связано: JPA Hibernate и JDBC сравнение интерфейсов, SQL инъекции, Транзакции принцип ACID.