← Назад к вопросам
Что есть внутри объектов для работы бизнес-процессов
2.2 Middle🔥 61 комментариев
#SOLID и паттерны проектирования#ООП
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что есть внутри объектов для работы бизнес-процессов
Объекты для работы бизнес-процессов — это основа, на которой строится вся логика приложения. Рассмотрю, что в них содержится и как они используются.
1. Entity классы (Сущности БД)
Это объекты, которые напрямую соответствуют таблицам в базе данных:
@Entity
@Table(name = "orders")
public class Order {
// Идентификаторы
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// Бизнес-данные
@Column(nullable = false)
private String orderNumber; // Номер заказа
@Enumerated(EnumType.STRING)
private OrderStatus status; // Статус: NEW, PROCESSING, COMPLETED
@Column(nullable = false)
private BigDecimal totalAmount; // Сумма заказа
@Column(nullable = false)
private LocalDateTime createdAt; // Дата создания
@Column
private LocalDateTime completedAt; // Дата завершения
// Связи с другими сущностями
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User customer; // Кто заказал
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items; // Товары в заказе
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "payment_id")
private Payment payment; // Платеж
// Служебные поля
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // Когда создан
@Column(nullable = false)
private LocalDateTime updatedAt; // Когда изменен
@Version
private Long version; // Для оптимистичной блокировки
// Методы бизнес-логики
public void cancel(String reason) {
if (this.status != OrderStatus.NEW) {
throw new InvalidOperationException("Can only cancel new orders");
}
this.status = OrderStatus.CANCELLED;
this.cancelReason = reason;
}
public void complete() {
if (this.status != OrderStatus.PROCESSING) {
throw new InvalidOperationException("Can only complete processing orders");
}
this.status = OrderStatus.COMPLETED;
this.completedAt = LocalDateTime.now();
}
}
2. Value Objects (Объекты значений)
Это простые объекты, которые не имеют идентификатора и используются как значения:
// Встроенный Value Object
@Embeddable
public class Address {
@Column(nullable = false)
private String street;
@Column(nullable = false)
private String city;
@Column(nullable = false)
private String zipCode;
@Column(nullable = false)
private String country;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Address)) return false;
Address address = (Address) o;
return Objects.equals(street, address.street) &&
Objects.equals(city, address.city) &&
Objects.equals(zipCode, address.zipCode) &&
Objects.equals(country, address.country);
}
@Override
public int hashCode() {
return Objects.hash(street, city, zipCode, country);
}
}
// Использование в Entity
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
@Column(nullable = false)
private String email;
// Встроенный Value Object
@Embedded
private Address shippingAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "street", column = @Column(name = "billing_street")),
@AttributeOverride(name = "city", column = @Column(name = "billing_city"))
// ...
})
private Address billingAddress;
}
// Другой пример: Money Value Object
public class Money {
private final BigDecimal amount;
private final String currency; // USD, EUR, RUB
public Money(BigDecimal amount, String currency) {
if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("Amount cannot be negative");
}
this.amount = amount;
this.currency = currency;
}
public Money add(Money other) {
if (!this.currency.equals(other.currency)) {
throw new IllegalArgumentException("Cannot add different currencies");
}
return new Money(this.amount.add(other.amount), this.currency);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Money)) return false;
Money money = (Money) o;
return Objects.equals(amount, money.amount) &&
Objects.equals(currency, money.currency);
}
}
3. Data Transfer Objects (DTO)
Это объекты для передачи данных между слоями и по сети:
// Request DTO (входящие данные)
public class CreateOrderRequest {
@NotEmpty(message = "Order items cannot be empty")
private List<OrderItemRequest> items; // Что заказывает клиент
@NotNull(message = "Shipping address is required")
private AddressDto shippingAddress;
@NotNull(message = "Payment method is required")
private String paymentMethod; // CREDIT_CARD, PAYPAL
// Getters
public List<OrderItemRequest> getItems() { return items; }
public AddressDto getShippingAddress() { return shippingAddress; }
public String getPaymentMethod() { return paymentMethod; }
}
// Response DTO (исходящие данные)
public class OrderResponse {
private Long id;
private String orderNumber;
private OrderStatus status;
private BigDecimal totalAmount;
private String currency;
private LocalDateTime createdAt;
private LocalDateTime completedAt;
private UserResponse customer; // Информация о покупателе
private List<OrderItemResponse> items; // Товары в заказе
private PaymentResponse payment; // Информация о платеже
// Getters
public Long getId() { return id; }
public String getOrderNumber() { return orderNumber; }
// ...
}
// Пример маппинга Entity → DTO
@Service
public class OrderService {
public OrderResponse getOrder(Long id) {
Order order = orderRepository.findById(id)
.orElseThrow(() -> new OrderNotFoundException(id));
// Маппируем Entity в DTO
return new OrderResponse(
order.getId(),
order.getOrderNumber(),
order.getStatus(),
order.getTotalAmount(),
order.getCurrency(),
order.getCreatedAt(),
order.getCompletedAt(),
mapUserToResponse(order.getCustomer()),
mapItemsToResponse(order.getItems()),
mapPaymentToResponse(order.getPayment())
);
}
}
4. Service Objects (Объекты для бизнес-логики)
Это объекты, которые содержат бизнес-логику:
// Сервис для работы заказов
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentService paymentService;
private final EmailService emailService;
private final InventoryService inventoryService;
// Процесс создания заказа
@Transactional
public OrderResponse createOrder(CreateOrderRequest request, Long userId) {
// 1. Валидируем входные данные
validateOrderRequest(request);
// 2. Получаем пользователя
User user = userService.getUserById(userId);
// 3. Проверяем доступность товаров
for (OrderItemRequest itemReq : request.getItems()) {
Product product = productService.getProduct(itemReq.getProductId());
if (product.getStock() < itemReq.getQuantity()) {
throw new InsufficientStockException(product.getId());
}
}
// 4. Создаем новый заказ
Order order = new Order();
order.setOrderNumber(generateOrderNumber());
order.setStatus(OrderStatus.NEW);
order.setCustomer(user);
order.setTotalAmount(calculateTotal(request.getItems()));
order.setShippingAddress(mapAddress(request.getShippingAddress()));
// 5. Добавляем товары
for (OrderItemRequest itemReq : request.getItems()) {
OrderItem item = new OrderItem();
item.setProduct(productService.getProduct(itemReq.getProductId()));
item.setQuantity(itemReq.getQuantity());
item.setPrice(item.getProduct().getPrice());
order.addItem(item);
}
// 6. Сохраняем заказ
order = orderRepository.save(order);
// 7. Создаем платеж
Payment payment = paymentService.createPayment(
order.getTotalAmount(),
request.getPaymentMethod(),
user.getPaymentDetails()
);
order.setPayment(payment);
orderRepository.save(order);
// 8. Зарезервируем товары
inventoryService.reserveItems(order);
// 9. Отправляем уведомление
emailService.sendOrderConfirmation(user.getEmail(), order);
return mapToResponse(order);
}
// Процесс отмены заказа
@Transactional
public void cancelOrder(Long orderId, String reason) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
// Проверяем статус
if (order.getStatus() != OrderStatus.NEW) {
throw new InvalidOperationException("Cannot cancel completed order");
}
// Отменяем заказ
order.cancel(reason);
// Отменяем платеж
if (order.getPayment() != null) {
paymentService.refund(order.getPayment());
}
// Освобождаем зарезервированные товары
inventoryService.unreserveItems(order);
// Сохраняем изменения
orderRepository.save(order);
// Уведомляем пользователя
emailService.sendCancellationNotification(order.getCustomer().getEmail(), order);
}
}
5. Command Objects (Команды для операций)
Объекты, которые представляют операции/команды:
// Command для создания заказа
public class CreateOrderCommand {
private final Long userId;
private final List<OrderItemRequest> items;
private final AddressDto shippingAddress;
private final String paymentMethod;
public CreateOrderCommand(Long userId, List<OrderItemRequest> items,
AddressDto shippingAddress, String paymentMethod) {
this.userId = userId;
this.items = items;
this.shippingAddress = shippingAddress;
this.paymentMethod = paymentMethod;
}
// Getters
}
// Command Handler
@Service
public class OrderCommandHandler {
private final OrderService orderService;
public OrderResponse handle(CreateOrderCommand command) {
return orderService.createOrder(
new CreateOrderRequest(command.getItems(), command.getShippingAddress(),
command.getPaymentMethod()),
command.getUserId()
);
}
}
6. Event Objects (События в системе)
Объекты, которые представляют события, произошедшие в системе:
// Событие: заказ создан
public class OrderCreatedEvent {
private final Long orderId;
private final String orderNumber;
private final Long userId;
private final BigDecimal amount;
private final LocalDateTime createdAt;
public OrderCreatedEvent(Long orderId, String orderNumber, Long userId,
BigDecimal amount, LocalDateTime createdAt) {
this.orderId = orderId;
this.orderNumber = orderNumber;
this.userId = userId;
this.amount = amount;
this.createdAt = createdAt;
}
}
// Event Listener
@Component
public class OrderEventListener {
private final EmailService emailService;
private final NotificationService notificationService;
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// Отправить email
emailService.sendOrderConfirmation(event);
// Отправить уведомление
notificationService.notify(event.getUserId(),
"Your order " + event.getOrderNumber() + " has been created");
}
}
Итоговая структура объектов
Database Layer
↓
Entity Objects (Order, User, Product)
↓
Value Objects (Money, Address)
↓
Service Layer (OrderService, PaymentService)
↓
DTO Objects (CreateOrderRequest, OrderResponse)
↓
Command/Event Objects (CreateOrderCommand, OrderCreatedEvent)
↓
REST Controller
↓
Client
Каждый уровень отвечает за свою ответственность и содержит соответствующие данные и методы для работы с бизнес-процессами.