← Назад к вопросам

Считаешь ли ошибкой сохранение контекста заявки в базе данных

2.0 Middle🔥 91 комментариев
#SOLID и паттерны проектирования#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сохранение контекста заявки в базе данных: анализ подхода

Это не ошибка, а скорее стратегический выбор, зависящий от конкретного контекста приложения. Мой взгляд на этот вопрос сложился через опыт различных проектов.

Когда сохранение контекста в БД оправданно

1. Аудит и законодательные требования В финансовых системах и системах лояльности часто требуется сохранять полный контекст заявки:

  • История изменений
  • Состояние всех параметров на момент обработки
  • Информацию для расследования спорных ситуаций
@Entity
public class ApplicationRequest {
  @Id
  private UUID id;
  
  @Column(columnDefinition = "jsonb") // PostgreSQL JSONB
  private String contextSnapshot; // Снимок контекста
  
  private LocalDateTime createdAt;
  private RequestStatus status;
}

2. Асинхронная обработка Когда заявка обрабатывается в несколько этапов, контекст должен быть сохранён:

  • Пользователь отправляет заявку
  • Система сохраняет контекст
  • Worker обрабатывает в фоне, используя сохранённый контекст

3. Восстановление после сбоев При падении сервиса можно восстановить состояние:

public class ApplicationProcessor {
  public void processWithRecovery(UUID requestId) {
    ApplicationRequest request = repository.findById(requestId);
    // Восстанавливаем контекст из БД
    ProcessingContext context = 
      objectMapper.readValue(request.getContextSnapshot(), 
      ProcessingContext.class);
    // Продолжаем с этого момента
  }
}

Когда это может быть проблемой

1. Избыточное дублирование Если контекст полностью дублирует данные из других таблиц и никогда не используется для восстановления, это загромождает БД:

// ❌ Плохо: дублируем то, что есть в других таблицах
status: "ACTIVE",
user.name: "John", // есть в users таблице
user.email: "john@mail.com", // есть в users таблице
product.price: 299.99 // есть в products таблице

2. Проблемы консистентности Если контекст несинхронизирован с основными данными:

// ❌ Проблема: контекст говорит одно, БД другое
// ApplicationRequest.contextSnapshot сохранён с ценой 299.99
// Но в products таблице цена изменилась на 399.99
// Какую использовать при апелляции?

3. Производительность Очень большие контексты (особенно JSON) могут замедлить запросы если они часто читаются.

Мой рекомендуемый подход

Гибридная стратегия:

@Entity
public class ApplicationRequest {
  @Id
  private UUID id;
  
  // Основные данные - связи с сущностями
  @ManyToOne
  private User applicant;
  
  @ManyToOne
  private Product product;
  
  // Контекст сохраняется ТОЛЬКО для:
  // 1. Данных, которые могут измениться в будущем
  @Column(columnDefinition = "jsonb")
  private String immutableContext; // Стоимость доставки на дату подачи
  
  // 2. Сложных объектов, которые нужны редко
  @Column(columnDefinition = "jsonb")
  private String processingMetadata; // Данные промежуточных шагов
  
  private ApplicationStatus status;
  private LocalDateTime createdAt;
}

Вопросы для определения подхода

  1. Нужен ли контекст для восстановления? → Да → сохраняй
  2. Требуется ли аудит? → Да → сохраняй в structured виде
  3. Контекст может измениться? → Да → сохраняй снимок
  4. Будешь ли ты использовать контекст в будущем? → Нет → не сохраняй

Практический пример из реального проекта

В системе лояльности мы решили сохранять минимальный контекст:

public class AcquisitionRequest {
  // Минимальный контекст
  private LocalDateTime applicationDate;
  private BigDecimal discountRateAtTime; // Важно: может меняться
  private String deviceType; // Может быть важно для анализа
  
  // НЕ сохраняем: user.fullName, product.description
  // Они в других таблицах
}

Заключение

Сохранение контекста заявки в БД — это не ошибка, а инструмент. Используй его когда:

  • Нужен аудит и восстановление
  • Данные контекста могут измениться
  • Контекст редко читается (чтобы не влиять на производительность)

Избегай когда:

  • Дублируется информация из других таблиц
  • Контекст никогда не используется
  • Это усложняет запросы без очевидной пользы