Курс "Промышленное программирование на Java". Набор лекций 3. "Реляционные базы данных".
Модель предметной области. Подключение к РСУБД из Java.
Spring JDBC.
МФТИ, 2014 год. Лектор - Лаврентьев Федор Сергеевич
3. Цели проектирования модели П.О.
Точно отразить реальные взаимосвязи
между сущностями
Упростить логическую структуру БД
Обеспечить удобное использование БД
Облегчить возможную эволюцию модели
Оптимально использовать физические
возможности машины
6. Нормализация
Проектирование начинается с одной
условной супертаблицы (отношения)
Нормализация - декомпозиция отношения с
выделением меньших отношений и связей
между ними
Выделяют не менее 5 нормальных форм
Задача - свести исходное отношение к
приемлемой нормальной форме
8. Индекс
Физическая реализация вторичного ключа
Компактно организованная структура
Осуществляет поиск записи по значению
ключа - помогает ускорить запросы
Осуществляет проверку условия
(constraint) на пространстве ключей
9. Реализация индекса
Как правило, физически хранится отдельно от
таблицы
Содержит только данные ключа и ссылки на
соответствующие записи
Организован в виде структуры поиска -
дерево поиска, хеш-таблица, гистограмма
Может храниться в памяти или на диске, в
зависимости от этого - разные реализации
10. Взаимосвязь
Термин - внешний ключ (Foreign Key)
Столбец-ссылка, указывает на ключ в
другой таблице
Физически реализуется в виде ссылки на
индекс в другой таблице
Использование ссылок позволяет СУБД
переходить сразу к нужной записи
11. Типы взаимосвязи
1:(0..1) “Один к одному”. Вспомогательная
таблица либо дополнительные столбцы
1:* - “Один к многим”. Внешний ключ.
*:* - “Многие ко многим”. Промежуточная
таблица с двумя внешними ключами.
12. Планирование запросов
СУБД составляет план выполнения
каждого запроса с учетом физической
организации данных
В плане выполнения задействуются
индексы и связи между таблицами
При проектировании нужно убедиться, что
планы выполнения наиболее важных
запросов выстраиваются оптимально
13. Эффект от индексов
На построение и обновление индекса
тратится время - замедляется вставка,
удаление и модификация
Можно быстро перейти к записи по
значению вторичного ключа
При работе с внешними ключами часть
операций можно производить на индексе
14. Результат проектирования
Список таблиц с заголовками
Механизмы генерации идентификаторов
Запланированные индексы (с типами)
Связи между таблицами
Сводный обзор планов выполнения
важнейших запросов
16. SQL CLI
sql> create table animals (id integer, name varchar,
weight decimal);
sql> show tables;
TABLE_NAME | TABLE_SCHEMA
ANIMALS | PUBLIC
sql> insert into animals values (1, 'kitten', 2.5);
sql> select name from animals where weight < 3.0;
NAME
kitten
17. JDBC
Open DataBase Connectivity (1992) -
унифицированное API SQL баз данных
Java DataBase Connectivity (1997) -
унифицированное Java API SQL БД
Изначально JDBC просто оборачивало
ODBC, однако потом были написаны
нативные реализации
18. Пример JDBC
Class.forName("com.mysql.jdbc.Driver"); // Загрузка
драйвера
String url = "jdbc:mysql://localhost:3306/db_name";
Connection conn =
DriverManager.getConnection(url, user, pass);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
while (rs.next()) {
// Process row
}
stmt.close();
19. Проблема - слишком много букв
Ручное управление подключениями
Ручное управление запросами к базе
Ручное управление транзакциями
Отсутствие конкурентного доступа
Опасности при закрытии ресурсов
Низкоуровневое API для данных
Сложная работа с исключениями
20. Решение - Spring JDBC
Расширение Spring Framework
Управляет подключениями и запросами
Вовремя закрывает дескрипторы
Тесно интегрировано с JTA и Spring
Transactions (см далее)
Каноничная иерархия исключений
Высокоуровневое API для запросов
21. Пример Spring JDBC
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
int updated = jdbcTemplate.update(
"insert into animals " +
"(id, name, weight) " +
"values (1, 'kitten', 2.5)");
List<String> names = jdbcTemplate.queryForList(
"select name from animals " +
"where weight < 3.0", String.class);
jdbcTemplate.execute("alter table animals " +
"add column (height decimal)");
25. Connection Pooling
Spring DataSource на каждый запрос
открывает новые подключения
Выгодно многократно переиспользовать
созданные подключения
Это сложная задача с массой нюансов
Есть готовые реализации - C3P0, DBCP,
BoneCP
27. JDBC Template
JdbcTemplate - класс-фасад, центральный
класс Spring JDBC
Предоставляет методы для упрощенной
работы с JDBC
Создается вокруг конкретного DataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
28. Методы JDBC Template
jdbcTemplate.execute(
“alter table users add column (last_login timestamp)”);
int count = jdbcTemplate.queryForObject(
“select count(*) from table”, Integer.class);
String userName = jdbcTemplate.queryForObject(
“select name from users where uid = 1”, String.class);
List<String> admins = jdbcTemplate.queryForList(
“select name from users where is_admin = 1”,
String.class);
Map<String, Object> row3 = jdbcTemplate.queryForMap(
“select * from rows where row = 3”);
29. Методы JDBC Template
int inserted = jdbcTemplate.update(
“insert into animals (id, name, weight) ” +
“values (1, ‘kitten’, 2.5)”);
int updated = jdbcTemplate.update(
“update animals set is_heavy = 1 where weight > 50”);
int deleted = jdbcTemplate.update(
“delete from animals where is_heavy = 0”);
33. Row Callback
class MeanCallback implements RowCallbackHandler {
double sum = 0;
int count = 0;
public double getMean() { return sum/count; }
public void processRow(ResultSet rs) {
sum += rs.getDouble(1);
count += 1;
}
}
34. Row Callback
MeanCallback callback = new MeanCallback();
String sql = "select weight from animals where in_zoo =
1";
jdbcTemplate.query(sql, callback);
double mean = callback.getMean();
35. Стандартизация исключений
В JDBC фигурирует checked SQLException
У каждого вендора свой подход к ошибкам
Исключения в транзакционной среде
требуют внимательной обработки
Spring берет на себя разбор исключений
Он использует свою unchecked иерархию
Маппинги пишутся отдельно к каждому
вендору (много доступно из коробки)
36. Prepared Statement
Стадии обработки SQL-запроса:
Передача текста запроса
Парсинг в синтаксическое дерево
Построение плана выполнения
Выполнение (вжжжж!)
Для массовых однотипных запросов
“планировочные” стадии несут оверхед
Есть возможность избежать этого
37. Prepared Statement
Запрос с Placeholder’ами:
select count(*) from animals where
weight >= ? and weight < ? and
country_id = 4;
Отправим запрос на сервер:
Передача текста запроса
Парсинг в синтаксическое дерево
Построение плана выполнения
Запомним ID запроса
38. Prepared Statement
Для запроса достаточно отправить только
ID и значения Placeholder’ов
Экономия на передаче данных, парсинге
текста и построении плана
Для легких запросов это >50% времени
39. Prepared Statement
static ANIMAL_ROW_MAPPER = new RowMapper<Animal>() {...}
for (int animalId : animalIds) {
Animal animal = jdbcTemplate.queryForObject(
"select * from animals where id = ? ",
animalId, ANIMAL_ROW_MAPPER);
animalsInZoo.add(animal);
jdbcTemplate.update(
"update animals set in_zoo = 1 where id = ? ",
animalId);
}