一、系统设计目标 1.实现商品信息的全生命周期管理 2.记录商品从上线到下架的所有变更历史 3.支持商品版本回滚和差异对比 4.提供审计追踪功能 二、核心功能模块 1.商品基本信息管理 -商品ID、名称、分类、品牌等基础信息 -商品状态(上架/下架/预售/缺货等)
一、系统设计目标
1. 实现商品信息的全生命周期管理
2. 记录商品从上线到下架的所有变更历史
3. 支持商品版本回滚和差异对比
4. 提供审计追踪功能
二、核心功能模块
1. 商品基本信息管理
- 商品ID、名称、分类、品牌等基础信息
- 商品状态(上架/下架/预售/缺货等)
- 商品上下架时间记录
2. 商品迭代记录表设计
```sql
CREATE TABLE product_version_history (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT NOT NULL COMMENT 商品ID,
version_number VARCHAR(20) NOT NULL COMMENT 版本号,
change_type ENUM(CREATE,UPDATE,DELETE) NOT NULL COMMENT 变更类型,
change_content JSON NOT NULL COMMENT 变更内容(JSON格式),
operator VARCHAR(50) NOT NULL COMMENT 操作人,
operation_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 操作时间,
reason VARCHAR(255) COMMENT 变更原因,
previous_version VARCHAR(20) COMMENT 前版本号,
INDEX idx_product_id (product_id),
INDEX idx_operation_time (operation_time)
);
```
3. 商品快照表设计(可选)
```sql
CREATE TABLE product_snapshots (
snapshot_id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT NOT NULL,
version_number VARCHAR(20) NOT NULL,
snapshot_data JSON NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_product_version (product_id, version_number)
);
```
三、关键实现逻辑
1. 商品创建流程
```java
public Product createProduct(ProductDTO productDTO, String operator) {
// 1. 生成商品唯一ID
Long productId = generateProductId();
// 2. 创建当前版本商品
Product product = convertToProduct(productDTO, productId);
productRepository.save(product);
// 3. 记录迭代历史
ProductVersionHistory history = new ProductVersionHistory();
history.setProductId(productId);
history.setVersionNumber("1.0.0"); // 初始版本
history.setChangeType(ChangeType.CREATE);
history.setChangeContent(convertToJson(productDTO));
history.setOperator(operator);
history.setReason("商品首次创建");
versionHistoryRepository.save(history);
// 4. 创建快照(可选)
createSnapshot(productId, "1.0.0", product);
return product;
}
```
2. 商品更新流程
```java
public Product updateProduct(Long productId, ProductUpdateDTO updateDTO, String operator) {
// 1. 获取当前商品最新版本
Product currentProduct = productRepository.findById(productId)
.orElseThrow(() -> new BusinessException("商品不存在"));
// 2. 计算新版本号(示例: 1.0.0 → 1.0.1)
String newVersion = calculateNewVersion(currentProduct.getVersionNumber());
// 3. 应用更新
applyUpdates(currentProduct, updateDTO);
currentProduct.setVersionNumber(newVersion);
productRepository.save(currentProduct);
// 4. 记录变更历史
Map
changeDiff = calculateDiff(currentProduct, updateDTO);
ProductVersionHistory history = new ProductVersionHistory();
history.setProductId(productId);
history.setVersionNumber(newVersion);
history.setChangeType(ChangeType.UPDATE);
history.setChangeContent(changeDiff);
history.setOperator(operator);
history.setReason(updateDTO.getReason());
history.setPreviousVersion(currentProduct.getVersionNumber()); // 旧版本号
versionHistoryRepository.save(history);
// 5. 创建快照(可选)
createSnapshot(productId, newVersion, currentProduct);
return currentProduct;
}
```
3. 版本差异计算实现
```java
private Map calculateDiff(Product oldProduct, ProductUpdateDTO updateDTO) {
Map diff = new HashMap<>();
// 示例: 比较价格变化
if (!Objects.equals(oldProduct.getPrice(), updateDTO.getPrice())) {
diff.put("price", Map.of(
"old", oldProduct.getPrice(),
"new", updateDTO.getPrice()
));
}
// 比较库存变化
if (!Objects.equals(oldProduct.getStock(), updateDTO.getStock())) {
diff.put("stock", Map.of(
"old", oldProduct.getStock(),
"new", updateDTO.getStock()
));
}
// 可以添加更多字段比较...
return diff;
}
```
四、高级功能实现
1. 版本回滚实现
```java
public Product rollbackToVersion(Long productId, String targetVersion, String operator) {
// 1. 获取目标版本快照
ProductSnapshot snapshot = snapshotRepository.findByProductIdAndVersion(productId, targetVersion)
.orElseThrow(() -> new BusinessException("目标版本不存在"));
// 2. 获取当前最新版本
Product currentProduct = productRepository.findById(productId)
.orElseThrow(() -> new BusinessException("商品不存在"));
// 3. 创建回滚版本号(示例: 1.0.3 → 1.0.3-rollback)
String rollbackVersion = targetVersion + "-rollback";
// 4. 应用快照数据
Product rolledBackProduct = convertSnapshotToProduct(snapshot);
rolledBackProduct.setVersionNumber(rollbackVersion);
productRepository.save(rolledBackProduct);
// 5. 记录回滚历史
ProductVersionHistory history = new ProductVersionHistory();
history.setProductId(productId);
history.setVersionNumber(rollbackVersion);
history.setChangeType(ChangeType.UPDATE);
history.setChangeContent(Map.of(
"action" => "rollback",
"fromVersion" => currentProduct.getVersionNumber(),
"toVersion" => targetVersion
));
history.setOperator(operator);
history.setReason("版本回滚到 " + targetVersion);
versionHistoryRepository.save(history);
return rolledBackProduct;
}
```
2. 变更审计查询
```java
public Page queryVersionHistory(Long productId,
LocalDateTime startTime, LocalDateTime endTime, Pageable pageable) {
// 构建查询条件
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(ProductVersionHistory.class);
Root root = query.from(ProductVersionHistory.class);
List predicates = new ArrayList<>();
if (productId != null) {
predicates.add(cb.equal(root.get("productId"), productId));
}
if (startTime != null) {
predicates.add(cb.greaterThanOrEqualTo(root.get("operationTime"), startTime));
}
if (endTime != null) {
predicates.add(cb.lessThanOrEqualTo(root.get("operationTime"), endTime));
}
query.where(predicates.toArray(new Predicate[0]));
query.orderBy(cb.desc(root.get("operationTime")));
TypedQuery typedQuery = entityManager.createQuery(query);
typedQuery.setFirstResult((int) pageable.getOffset());
typedQuery.setMaxResults(pageable.getPageSize());
// 获取总数
CriteriaQuery countQuery = cb.createQuery(Long.class);
countQuery.select(cb.count(countQuery.from(ProductVersionHistory.class)));
if (!predicates.isEmpty()) {
countQuery.where(predicates.toArray(new Predicate[0]));
}
Long total = entityManager.createQuery(countQuery).getSingleResult();
return new PageImpl<>(typedQuery.getResultList(), pageable, total);
}
```
五、性能优化建议
1. 异步处理:对于非关键的版本记录操作,可以采用异步方式处理
2. 批量插入:对于大量商品变更,使用批量插入优化性能
3. 索引优化:确保版本记录表的关键字段有适当索引
4. 归档策略:对历史版本数据实施归档策略,保留最近N个版本在线
5. 缓存机制:对频繁查询的商品版本信息使用缓存
六、扩展功能考虑
1. 变更通知:当关键商品属性变更时,自动通知相关系统或人员
2. 变更影响分析:分析商品变更对订单、库存等系统的影响
3. 多环境同步:支持开发、测试、生产环境的版本同步
4. AB测试支持:记录不同版本的商品在不同用户群体的表现
以上方案可根据叮咚买菜实际业务需求和技术栈进行调整和优化。