Перейти к основному содержимому

Работа приложений с базами данных

Разработчику Аналитику Тестировщику
Архитектору Инженеру


Работа приложений с базами данных

Теперь поговорим о том, как работают с данными в программировании. Так, мы изучили объектно-ориентированное программирование (ООП) и изучили реляционные базы данных (SQL), определили, что есть программирование логики, а есть хранение и обработка данных.

Но как программы взаимодействуют с базами данных?

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

И для этого нужно ещё раз пробежаться по SQL с точки зрения практического применения. Мы изучили функционал. А на практике как?


Задачи

Play ITЗагрузка интерактивного демо…

Play ITЗагрузка интерактивного демо…

Play ITЗагрузка интерактивного демо…

★ Какие задачи решает база данных?

  • хранение данных;
  • выбор данных;
  • добавление данных;
  • изменение данных;
  • удаление данных.
  • подсчёт данных;
  • сортировка, группировка и многие другие функции.

Давайте разберём эти задачи.


Хранение данных

БД предназначены для надёжного хранения информации. Они обеспечивают структурированное представление данных, что позволяет легко находить, изменять и управлять ими.

Пример - интернет-магазин может хранить информацию о товарах, клиентах, заказах и платежах - и всё это будет в разных таблицах, связанных между собой.


НазваниеЦенаКоличество
Товар110053
Товар220096
Товар330011
ИмяАдресEMail
ИвановМосква1@mail.ru
ПетровКазань2@mail.ru
СидоровУфа3@mail.ru
ТоварыДатаСтатус
1, 2, 325.05.2025Готов
114.02.2024Готов
322.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
ControllerHTTP, коды ответовнет
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, не сущности БД.

Типовые вопросы на собеседовании

  1. Чем отличается задача БД от задачи приложения?
  2. Для чего нужен индекс на поле поиска?
  3. Почему SELECT * без WHERE опасен на больших таблицах?
  4. Где в архитектуре должен жить SQL — в контроллере или репозитории?
  5. Зачем отделять DTO от ORM-сущности при ответе API?

Мини-практикум

  1. Для интернет-магазина перечислите 5 таблиц и связи между ними.
  2. Напишите SQL выборки товаров дешевле 50 000 и тот же запрос словами ORM.
  3. Нарисуйте слои от HTTP до PostgreSQL для одного endpoint.