Работа приложений с базами данных
Разработчику
Аналитику
Тестировщику
Архитектору
Инженеру
Работа приложений с базами данных
Теперь поговорим о том, как работают с данными в программировании. Так, мы изучили объектно-ориентированное программирование (ООП) и изучили реляционные базы данных (SQL), определили, что есть программирование логики, а есть хранение и обработка данных.
Но как программы взаимодействуют с базами данных?
Прежде, чем мы перейдём к особенностям различных языков программирования, нам нужно изучить универсальный подход по работе с базой данных.
И для этого нужно ещё раз пробежаться по SQL с точки зрения практического применения. Мы изучили функционал. А на практике как?
Задачи
Play ITЗагрузка интерактивного демо…
Play ITЗагрузка интерактивного демо…
Play ITЗагрузка интерактивного демо…
★ Какие задачи решает база данных?
- хранение данных;
- выбор данных;
- добавление данных;
- изменение данных;
- удаление данных.
- подсчёт данных;
- сортировка, группировка и многие другие функции.
Давайте разберём эти задачи.
Хранение данных
БД предназначены для надёжного хранения информации. Они обеспечивают структурированное представление данных, что позволяет легко находить, изменять и управлять ими.
Пример - интернет-магазин может хранить информацию о товарах, клиентах, заказах и платежах - и всё это будет в разных таблицах, связанных между собой.
| Название | Цена | Количество |
|---|---|---|
| Товар1 | 100 | 53 |
| Товар2 | 200 | 96 |
| Товар3 | 300 | 11 |
| Имя | Адрес | |
|---|---|---|
| Иванов | Москва | 1@mail.ru |
| Петров | Казань | 2@mail.ru |
| Сидоров | Уфа | 3@mail.ru |
| Товары | Дата | Статус |
|---|---|---|
| 1, 2, 3 | 25.05.2025 | Готов |
| 1 | 14.02.2024 | Готов |
| 3 | 22.06.2025 | Готов |
И SQL как раз позволяет выполнять какие-то операции - поиск, добавление, обновление, удаление, агрегация.
Разберём подробнее.
Выбор данных
БД позволяет извлекать нужные данные с помощью запросов. Это может быть поиск конкретной записи или выборка по определённым критериям, что создаёт некий массив, коллекцию.
Пример - пользователь интернет-магазина выполняет поиск ноутбуков стоимостью до 50000 рублей. Запрос в БД выбирает все товары из категории "Ноутбуки" с ценой меньше или равной 50000. В этот момент выполняется SQL-запрос:
SELECT * FROM Products WHERE category = 'laptops' AND price <= 50000;
Добавление данных
Новые данные можно добавлять БД для поддержания актуальности информации.
Пример - владелец магазина добавляет новый товар - смартфон Xiaomi 13 Ultra:
INSERT INTO Products (name, category, price, stock)
VALUES ('Xiaomi 13 Ultra', 'smartphones', 79999, 50);
Обновление данных
Данные в БД можно изменять. Это полезно, когда информация становится устаревшей или меняется.
Пример - администратор магазина обновляет цену на iPhone 16 Pro с 150000 до 80000 рублей.
UPDATE Products
SET price = 80000
WHERE name = 'iPhone 16 Pro';
Удаление данных
Устаревшие или ненужные данные можно удалять из БД.
Пример - товар закончился на складе, и его больше не планируют продавать. Например, удаляем старую модель телефона:
DELETE FROM Products
WHERE name = 'iPhone 11';
Подсчёты и аналитика
БД позволяют выполнять расчёты и анализировать данные. Это может быть подсчёт количества записей, суммирование значений или вычисление средних значений.
Пример - магазин хочет узнать общую стоимость всех товаров на складе.
SELECT SUM(price * stock) AS total_stock_value
FROM Products;
Агрегатные функции
Те самые SUM, AVG, COUNT, MIN, MAX - они позволяют выполнять сложные вычисления на основе данных, получая результат сразу в нужном виде.
Пример - магазин хочет узнать среднюю цену всех товаров в категории ноутбуков.
SELECT AVG(price) AS average_price
FROM Products
WHERE category = 'laptops';
Индексы
Они ускоряют поиск данных в БД, работая как указатели, которые помогают быстро находить нужные записи.
Пример - в телефонной книге быстрее найти человека по фамилии, если она отсортирована по алфавиту. Аналогично, индекс в БД ускоряет поиск товаров по названию.
CREATE INDEX idx_product_name ON Products(name);
Сортировка данных
Сортировка позволяет упорядочивать данные по определённому критерию (по возрастанию, например).
Пример - клиент хочет увидеть товары, отсортированные по цене - от дешевых к дорогим.
SELECT * FROM Products
ORDER BY price ASC;
Группировка
БД могут группировать данные и создавать сводные отчеты. Это полезно для анализа больших объемов информации.
Пример - магазин хочет узнать, сколько товаров каждой категории есть на складе.
SELECT category, SUM(stock) AS total_stock
FROM Products
GROUP BY category;
Работа с большими данными
Современные БД способны обрабатывать огромные объемы данных, сохраняя высокую производительность.
Пример - сервис потокового видео (тот же Netflix) хранит данные о миллионах пользователей, их предпочтениях, истории просмотров и рекомендациях. Это - большие данные (BigData) и базы данных здесь играют ключевую роль.
Оптимизация
Конечно, примеров выше достаточно - у нас и индексы, и группировка, и сортировка, но как правило, этим не ограничивается.
И, кстати говоря, ещё один момент — оптимизация проектирования. Например, в примере выше мы используем перечисление товаров в таблице с Заказами, хотя лучше сделать промежуточную таблицу связи — об этом в проектировании баз данных.
Повторение SQL здесь связывает операции приложения с тем, что ORM генерирует под капотом. Следующий шаг — взаимодействие кода с СУБД и объектно-реляционное отображение.
Слои приложения и база данных
DTO (Data Transfer Object) — упрощённый объект для ответа API: только нужные поля, без служебных связей БД.
Типичная цепочка запроса:
| Слой | Задача | Знает ли SQL |
|---|---|---|
| Controller | HTTP, коды ответов | нет |
| Service | бизнес-правила, граница транзакции | нет |
| Repository | запросы к данным | через ORM |
| ORM | маппинг, генерация SQL | генерирует SQL |
Подробнее о слое данных — принципы проектирования ORM.
В ответ API не отдают сущности с навигационными свойствами (Order.Customer.Orders) — JSON раздувается и появляются циклы сериализации (FAQ).
Паттерн Repository (кратко)
ИНТЕРФЕЙС IOrderRepository
GetById(id)
ListForCustomer(customerId, skip, take)
Add(order)
КЛАСС OrderRepository
РЕАЛИЗУЕТ IOrderRepository
использует AppDbContext
Сервис зависит от интерфейса — в тестах подставляют fake. ORM остаётся внутри репозитория.
Транзакции на уровне сервиса
Одна бизнес-операция = одна транзакция:
МЕТОД CheckoutService.Complete(cartId)
НАЧАТЬ транзакцию
order := создать заказ из cart
списать остатки
очистить cart
COMMIT
Несколько вызовов SaveChanges внутри одной транзакции допустимы; несколько независимых транзакций для одного checkout — ошибка проектирования.
Чтение и запись
| Операция | Частота | Оптимизация |
|---|---|---|
| Чтение каталога | очень высокая | кэш, индексы, пагинация |
| Создание заказа | средняя | короткая транзакция |
| Ночной отчёт | низкая | отдельный SQL, replica |
ORM удобен для записи и типового чтения; тяжёлое чтение выносят (ограничения ORM).
Что запомнить
- БД решает хранение, выборку, изменение и аналитику; приложение формулирует запросы через SQL, ORM или API.
- CRUD в коде соответствует INSERT/SELECT/UPDATE/DELETE в SQL.
- Индексы, нормализация и пагинация важны до выбора ORM.
- Доступ к данным идёт через слои: API → сервис → репозиторий → ORM → СУБД.
- Контракт API — DTO, не сущности БД.
Типовые вопросы на собеседовании
- Чем отличается задача БД от задачи приложения?
- Для чего нужен индекс на поле поиска?
- Почему
SELECT *безWHEREопасен на больших таблицах? - Где в архитектуре должен жить SQL — в контроллере или репозитории?
- Зачем отделять DTO от ORM-сущности при ответе API?
Мини-практикум
- Для интернет-магазина перечислите 5 таблиц и связи между ними.
- Напишите SQL выборки товаров дешевле 50 000 и тот же запрос словами ORM.
- Нарисуйте слои от HTTP до PostgreSQL для одного endpoint.