重构所有注解@CacheConfig的Service类,将IEntityService泛型从实体类改为VO类 实现实体与VO之间的转换逻辑,使用VO替代实体进行缓存以避免序列化问题 更新相关依赖组件和测试用例,确保功能完整性和系统兼容性 优化Redis缓存配置,清理旧缓存数据并验证新缓存策略有效性
240 lines
8.0 KiB
Markdown
240 lines
8.0 KiB
Markdown
# Inventory 实体类说明文档
|
||
|
||
## 1. 概述
|
||
|
||
`Inventory` 类是 Contract-Manager 项目中的核心实体类,代表**存货物品清单**,用于管理和存储各类存货物品的详细信息。该类位于 `common` 模块中,实现了 `IdentityEntity`、`BasedEntity` 和 `Serializable` 接口,支持数据持久化和对象序列化。
|
||
|
||
## 2. 类结构
|
||
|
||
```java
|
||
@Getter
|
||
@Setter
|
||
@Entity
|
||
@Table(name = "INVENTORY", schema = "supplier_ms")
|
||
public class Inventory implements IdentityEntity, BasedEntity, Serializable {
|
||
// 类实现内容
|
||
}
|
||
```
|
||
|
||
### 2.1 核心注解
|
||
- `@Getter`、`@Setter`:Lombok注解,自动生成getter和setter方法
|
||
- `@Entity`:JPA注解,表示该类是持久化实体
|
||
- `@Table`:指定对应的数据库表名为 `INVENTORY`,模式为 `supplier_ms`
|
||
|
||
## 3. 字段说明
|
||
|
||
### 3.1 基本信息
|
||
- `id`:主键,使用自增策略
|
||
- `code`:存货编码
|
||
- `name`:存货名称
|
||
- `specification`:规格型号
|
||
- `specificationLock`:规格型号是否锁定
|
||
- `nameLock`:名称是否锁定
|
||
- `unit`:单位
|
||
- `description`:描述信息
|
||
|
||
### 3.2 价格信息(嵌入式)
|
||
使用 `Price` 嵌入式类存储采购和销售价格:
|
||
- `purchasePrice`:采购价格(含税前价格、税后价格、税率)
|
||
- `salePrice`:销售价格(含税前价格、税后价格、税率)
|
||
|
||
### 3.3 重量与尺寸信息
|
||
- `weight`:产品重量
|
||
- `packagedWeight`:包装重量
|
||
- `weightUnit`:重量单位(默认:kg)
|
||
- `volumeUnit`:体积单位(默认:m³)
|
||
- `sizeUnit`:尺寸单位(默认:mm)
|
||
|
||
### 3.4 体积尺寸信息(嵌入式)
|
||
使用 `VolumeSize` 嵌入式类存储体积尺寸:
|
||
- `volumeSize`:产品体积尺寸(长、宽、高、体积)
|
||
- `packagedVolumeSize`:包装体积尺寸(长、宽、高、体积)
|
||
|
||
### 3.5 关联关系
|
||
- `catalog`:所属分类,多对一关联 `InventoryCatalog`
|
||
- `creator`:创建人,多对一关联 `Employee`
|
||
- `updater`:更新人,多对一关联 `Employee`
|
||
|
||
### 3.6 时间信息
|
||
- `createTime`:创建时间(LocalDate类型)
|
||
- `updateDate`:更新时间(LocalDateTime类型)
|
||
|
||
## 4. 接口实现
|
||
|
||
### 4.1 IdentityEntity 接口
|
||
- 实现了 `getId()` 和 `setId(Integer id)` 方法
|
||
- 重写了 `equals(Object object)` 方法,基于ID进行比较
|
||
|
||
### 4.2 BasedEntity 接口
|
||
- 实现了 `toPrettyString()` 方法,返回 "名称+规格" 格式的字符串
|
||
|
||
## 5. 关联实体类
|
||
|
||
### 5.1 InventoryCatalog
|
||
- 表示存货分类
|
||
- 与Inventory是一对多关系
|
||
|
||
### 5.2 Price
|
||
- 嵌入式类,存储价格相关信息
|
||
- 包含税率、税前价格、税后价格
|
||
|
||
### 5.3 VolumeSize
|
||
- 嵌入式类,存储体积尺寸信息
|
||
- 包含体积、长度、宽度、高度
|
||
|
||
### 5.4 Employee
|
||
- 表示系统用户/员工
|
||
- 与Inventory是多对一关系(创建人和更新人)
|
||
|
||
## 6. 数据访问层
|
||
|
||
`InventoryRepository` 接口提供了对Inventory实体的数据库访问功能:
|
||
|
||
```java
|
||
@Repository
|
||
public interface InventoryRepository extends JpaRepository<Inventory, Integer>, JpaSpecificationExecutor<Inventory> {
|
||
Optional<Inventory> findByCode(String code);
|
||
}
|
||
```
|
||
|
||
- 继承自 `JpaRepository`,提供基本的CRUD操作
|
||
- 继承自 `JpaSpecificationExecutor`,支持动态查询条件
|
||
- 自定义方法 `findByCode`,通过编码查询存货
|
||
|
||
## 7. 服务层
|
||
|
||
### 7.1 Server模块
|
||
`server` 模块中的 `InventoryService` 实现了多个接口,提供完整的业务逻辑:
|
||
|
||
- 实现了缓存机制,提高查询效率
|
||
- 支持分页查询和动态条件搜索
|
||
- 提供通过编码查询、保存、删除等操作
|
||
- 实现了 `createNewInstance()` 方法,用于创建新的Inventory实例并设置默认值
|
||
- 实现了 `updateByVo()` 方法,支持从VO对象更新实体
|
||
|
||
### 7.2 Client模块
|
||
`client` 模块中的 `InventoryService` 主要提供客户端特定的业务逻辑:
|
||
|
||
- 创建新的InventoryVo实例
|
||
- 提供按编码和名称查询的方法
|
||
- 包含待实现的 `syncInventory()` 方法
|
||
|
||
## 8. 数据传输对象
|
||
|
||
`InventoryVo` 类用于在不同层之间传输Inventory相关数据:
|
||
|
||
- 包含与Inventory实体对应的主要字段
|
||
- 添加了 `active` 字段,表示状态
|
||
- 使用关联实体的ID替代直接引用(如 `catalogId`、`creatorId` 等)
|
||
|
||
## 9. 代码优化建议
|
||
|
||
### 9.1 数据一致性
|
||
- **问题**:`InventoryService.createNewInstance()` 方法设置了默认的税率为13%,但没有自动计算税后价格
|
||
- **建议**:
|
||
```java
|
||
public Inventory createNewInstance() {
|
||
Inventory inventory = new Inventory();
|
||
|
||
// 设置默认值
|
||
inventory.setNameLock(false);
|
||
inventory.setSpecificationLock(false);
|
||
|
||
// 设置税率并自动计算税后价格
|
||
float defaultTaxRate = 13;
|
||
double defaultPrice = 0;
|
||
|
||
Price purchasePrice = inventory.getPurchasePrice();
|
||
purchasePrice.setTaxRate(defaultTaxRate);
|
||
purchasePrice.setPreTaxPrice(defaultPrice);
|
||
purchasePrice.setPostTaxPrice(defaultPrice * (1 + defaultTaxRate / 100));
|
||
|
||
Price salePrice = inventory.getSalePrice();
|
||
salePrice.setTaxRate(defaultTaxRate);
|
||
salePrice.setPreTaxPrice(defaultPrice);
|
||
salePrice.setPostTaxPrice(defaultPrice * (1 + defaultTaxRate / 100));
|
||
|
||
// 其他默认值设置
|
||
inventory.setWeightUnit("kg");
|
||
inventory.setVolumeUnit("m³");
|
||
inventory.setSizeUnit("mm");
|
||
inventory.setCreateTime(LocalDate.now());
|
||
|
||
return inventory;
|
||
}
|
||
```
|
||
|
||
### 9.2 时间类型一致性
|
||
- **问题**:创建时间使用 `LocalDate` 类型,更新时间使用 `LocalDateTime` 类型,类型不一致
|
||
- **建议**:统一使用 `LocalDateTime` 类型,以便更精确地记录时间信息
|
||
|
||
### 9.3 完整性验证
|
||
- **问题**:缺少对必填字段的完整性验证
|
||
- **建议**:在 `save` 方法中添加基本的验证逻辑:
|
||
```java
|
||
@Caching(evict = {
|
||
@CacheEvict(key = "#p0.id"),
|
||
@CacheEvict(key = "'code-'+#p0.code"),
|
||
})public Inventory save(Inventory entity) {
|
||
// 基本验证
|
||
if (entity == null) {
|
||
throw new IllegalArgumentException("Inventory entity cannot be null");
|
||
}
|
||
if (!StringUtils.hasText(entity.getName())) {
|
||
throw new IllegalArgumentException("Inventory name is required");
|
||
}
|
||
|
||
// 更新时间戳
|
||
entity.setUpdateDate(LocalDateTime.now());
|
||
|
||
return inventoryRepository.save(entity);
|
||
}
|
||
```
|
||
|
||
### 9.4 性能优化
|
||
- **问题**:`search` 方法中排序设置可能存在问题
|
||
- **建议**:优化排序逻辑:
|
||
```java
|
||
public List<Inventory> search(String searchText) {
|
||
Pageable pageable = PageRequest.of(0, getSearchPageSize(), Sort.by(Sort.Direction.DESC, "id"));
|
||
Specification<Inventory> specification = getSpecification(searchText);
|
||
return inventoryRepository.findAll(specification, pageable).getContent();
|
||
}
|
||
```
|
||
|
||
## 10. 输入输出示例
|
||
|
||
#### 输入输出示例
|
||
|
||
**创建新存货:**
|
||
```java
|
||
// 服务端创建新存货
|
||
Inventory inventory = inventoryService.createNewInstance();
|
||
inventory.setName("笔记本电脑");
|
||
inventory.setCode("NB-001");
|
||
inventory.setSpecification("ThinkPad X1 Carbon");
|
||
inventory.setUnit("台");
|
||
|
||
// 设置价格信息
|
||
Price salePrice = inventory.getSalePrice();
|
||
salePrice.setPreTaxPrice(9999.00);
|
||
salePrice.setPostTaxPrice(9999.00 * 1.13);
|
||
|
||
// 保存
|
||
inventory = inventoryService.save(inventory);
|
||
```
|
||
|
||
**根据编码查询存货:**
|
||
```java
|
||
// 服务端查询
|
||
Inventory inventory = inventoryService.findByCode("NB-001");
|
||
System.out.println("存货名称:" + inventory.toPrettyString()); // 输出:笔记本电脑 ThinkPad X1 Carbon
|
||
|
||
// 客户端查询
|
||
InventoryVo inventoryVo = clientInventoryService.findByCode("NB-001");
|
||
System.out.println("存货ID:" + inventoryVo.getId() + ", 名称:" + inventoryVo.getName());
|
||
```
|
||
|
||
## 11. 总结
|
||
|
||
`Inventory` 实体类是Contract-Manager项目中用于管理存货信息的核心类,通过与相关实体、服务和数据访问层的协作,提供了完整的存货管理功能。该类设计合理,包含了存货的各种属性信息,并通过实现相关接口提供了标准的行为规范。通过实施建议的优化,可以进一步提高代码的健壮性、一致性和性能。 |