1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
| // CQRS 패턴 구현
// Command 측면
public abstract class Command {
private final UUID id = UUID.randomUUID();
private final LocalDateTime timestamp = LocalDateTime.now();
public UUID getId() { return id; }
public LocalDateTime getTimestamp() { return timestamp; }
}
public class CreateOrderCommand extends Command {
private final String customerId;
private final List<OrderItem> items;
public CreateOrderCommand(String customerId, List<OrderItem> items) {
this.customerId = customerId;
this.items = items;
}
// getters...
}
public interface CommandHandler<T extends Command> {
void handle(T command);
}
public class CreateOrderCommandHandler implements CommandHandler<CreateOrderCommand> {
private final EventStore eventStore;
public CreateOrderCommandHandler(EventStore eventStore) {
this.eventStore = eventStore;
}
@Override
public void handle(CreateOrderCommand command) {
String orderId = UUID.randomUUID().toString();
Order order = Order.create(orderId, command.getCustomerId(), command.getItems());
// 이벤트 저장
for (Event event : order.getUncommittedEvents()) {
eventStore.append(orderId, event);
}
order.markEventsAsCommitted();
}
}
// Query 측면
public class OrderSummaryView {
private final String orderId;
private final String customerId;
private final BigDecimal totalAmount;
private final OrderStatus status;
private final LocalDateTime createdAt;
public OrderSummaryView(String orderId, String customerId, BigDecimal totalAmount,
OrderStatus status, LocalDateTime createdAt) {
this.orderId = orderId;
this.customerId = customerId;
this.totalAmount = totalAmount;
this.status = status;
this.createdAt = createdAt;
}
// getters...
}
public class OrderQueryService {
private final Map<String, OrderSummaryView> orderSummaries = new ConcurrentHashMap<>();
// 이벤트 핸들러 (프로젝션 업데이트)
public void on(OrderCreatedEvent event) {
BigDecimal total = event.getItems().stream()
.map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
OrderSummaryView summary = new OrderSummaryView(
event.getOrderId(),
event.getCustomerId(),
total,
OrderStatus.CREATED,
LocalDateTime.now()
);
orderSummaries.put(event.getOrderId(), summary);
}
public void on(OrderShippedEvent event) {
OrderSummaryView existing = orderSummaries.get(event.getOrderId());
if (existing != null) {
OrderSummaryView updated = new OrderSummaryView(
existing.getOrderId(),
existing.getCustomerId(),
existing.getTotalAmount(),
OrderStatus.SHIPPED,
existing.getCreatedAt()
);
orderSummaries.put(event.getOrderId(), updated);
}
}
public List<OrderSummaryView> getOrdersByCustomer(String customerId) {
return orderSummaries.values().stream()
.filter(order -> order.getCustomerId().equals(customerId))
.collect(Collectors.toList());
}
}
|