9.2 KiB
Структура БД и модель данных
Документ описывает схемы PostgreSQL, которые используются приложением, а также слой абстракции на базе Ktorm ORM.
Технологический стек
- PostgreSQL – основная СУБД. Подключение выполняется через HikariCP (см.
app/Database.kt), параметры берутся из переменных окруженияDB_*. - Ktorm ORM – легковесная ORM, которая:
- предоставляет интерфейсы
Entityдля объектного представления строк; - описывает таблицы через
object Table<T>(например,object NewsT : Table<News>("t_news")); - дает
Database.sequenceOf(Table)для CRUD-операций и построения SQL через DSL.
- предоставляет интерфейсы
Каждая доменная сущность имеет:
interface <Entity> : Entity<<Entity>>– декларация полей.object <Table> : Table<<Entity>>("table_name")– описание колонок/ключей и связей черезbindTo/references.- DTO для сериализации в API.
Таблицы
t_admins
| Колонка | Тип | Описание |
|---|---|---|
id |
bigint (PK) |
Идентификатор администратора |
username |
varchar |
Уникальное имя пользователя |
password_hash |
varchar |
Хеш пароля (bcrypt) |
created_at |
timestamp |
Дата регистрации |
last_login_at |
timestamp nul. |
Время последней авторизации |
Сущность: AdminEntity, таблица: AdminUsers. Используется модулем admin для регистрации, логина, смены паролей и удаления аккаунтов.
t_news
| Колонка | Тип | Описание |
|---|---|---|
id |
bigint (PK) |
Идентификатор новости |
title |
varchar |
Заголовок |
slug |
varchar |
Уникальный slug для ссылок |
summary |
varchar |
Краткое описание |
content |
text |
Основной текст |
status |
varchar |
DRAFT | PUBLISHED | ARCHIVED |
published_at |
timestamp nul. |
Дата публикации |
image_url |
varchar nul. |
Ссылка на изображение |
created_at |
timestamp |
Дата создания |
updated_at |
timestamp |
Дата последнего обновления |
Сущность: News, таблица: NewsT. Репозиторий использует фильтры по статусу и slug для публичных и админских запросов.
t_service_categories
| Колонка | Тип | Описание |
|---|---|---|
id |
bigint (PK) |
Идентификатор категории |
name |
varchar |
Название |
slug |
varchar |
Уникальный slug |
Сущность: ServiceCategoryEntity, таблица: ServiceCategories. Используется как справочник категорий услуг.
t_services
| Колонка | Тип | Описание |
|---|---|---|
id |
bigint (PK) |
Идентификатор услуги |
title |
varchar |
Название |
slug |
varchar |
Уникальный slug |
description |
text |
Подробное описание |
price_from |
decimal nul. |
Нижняя граница стоимости |
image_url |
varchar nul. |
Изображение |
status |
varchar |
PUBLISHED | DRAFT | ARCHIVED |
category_id |
bigint FK |
Ссылка на t_service_categories.id (может быть NULL) |
created_at |
timestamp |
Дата создания |
updated_at |
timestamp |
Дата обновления |
Сущность: ServiceEntity, таблица: Services. Поле category смоделировано через references(ServiceCategories) и возвращает ServiceCategoryEntity?. Сервис объединяет услуги и категории для публичного и админского API.
t_users (лиды)
| Колонка | Тип | Описание |
|---|---|---|
id |
bigint (PK) |
Идентификатор лида |
full_name |
varchar |
Имя и фамилия |
email |
varchar |
Контактный email |
phone |
varchar nul. |
Телефон |
created_at |
timestamp |
Дата поступления заявки |
Сущность: LeadEntity, таблица: Leads. Несмотря на название таблицы t_users, фактически хранит только заявки. Админский модуль использует пагинацию и поиск по full_name/email.
Связи между сущностями
- Service → ServiceCategory (многие к одному):
Services.category_idссылается наServiceCategories.id. Ktorm позволяет навигировать черезServiceEntity.category. При выборе услуг можно жадно загружать категорию и формировать вложенный DTO. - Admin, News, Leads – независимые сущности без внешних ключей на другие таблицы (в текущей версии).
- Status/enum поля находятся в бизнес-логике: нет отдельных таблиц для статусов, их значения валидируются сервисами.
Использование Ktorm
-
Entity интерфейсы – объявляют свойства и их типы. Экземпляры создаются через
Entity.Factory. -
Table объекты – задают имя таблицы, колонки и связи. Пример:
object Services : Table<ServiceEntity>("t_services") { val title = varchar("title").bindTo { it.title } val category = long("category_id").references(ServiceCategories) { it.category } } -
Расширения Database – в каждом модуле есть свой
val Database.<entities>(например,Database.news) для полученияsequenceOf(Table):val Database.news get() = this.sequenceOf(NewsT)Это скрывает детали доступа к данным и дает типобезопасные операции (
filter,sortedBy,take,drop,insert,updateи т.д.). -
DTO слой – отделяет Ktorm-entity от сериализуемых объектов (например,
NewsDTO,ServiceDTO). Преобразование выполняется в сервисах.
Итог
База данных состоит из пяти основных таблиц, объединенных единым пулом соединений и общими практиками (таймстемпы, статусы, slug). Слабое связывание между сущностями делает схему гибкой, а Ktorm обеспечивает лаконичный и типобезопасный доступ к данным без тяжелых ORM-схем. Диаграмма CRUD-слоя (docs/crud-model.svg) дополняет данное описание визуальным представлением потока данных.