9.0 KiB
junboV2 项目上下文(Claude 参考文档)
本文档用于为 Claude AI 助手提供项目背景和关键决策上下文
项目概况
项目名称: junboV2 类型: 企业管理系统 技术栈: Spring Boot 2.7.18 + Spring Data JPA + SQLite + Lombok 构建工具: Gradle 7.6.3 Java 版本: Java 8 (1.8) JDK: 使用系统 JAVA_HOME 环境变量指定的 JDK
业务领域
- organization - 组织架构(员工、部门、部门关系)
- attendance - 考勤管理(签到、请假、工作日历)
- scrum - Scrum 迭代(Sprint、Story、Story Member)
- kpa - KPA 绩效(KPA 记录、员工得分)
- incentive - 激励管理(激励记录)
包结构(Package by Feature)
info.panli.junbo/
├── JunboApplication.java # Spring Boot 入口
├── api/ # REST Controllers(横切层)
├── infrastructure/ # 基础设施(横切层)
│ ├── config/ # 配置类
│ └── importer/ # 数据导入接口
├── organization/ # 【核心领域】组织架构
│ ├── entity/ # JPA 实体
│ ├── repository/ # Spring Data Repository
│ └── importer/ # 数据导入服务
├── attendance/ # 【业务领域】考勤
│ ├── entity/
│ ├── repository/
│ ├── importer/
│ ├── bo/, dao/, po/ # 旧代码(保留,标记 @Deprecated)
│ └── service/
├── scrum/ # 【业务领域】迭代
│ ├── entity/
│ ├── repository/
│ ├── service/
│ └── bo/, dao/, po/ # 旧代码(保留)
├── kpa/ # 【业务领域】KPA
│ ├── entity/
│ ├── repository/
│ ├── service/
│ └── bo/, dao/, po/ # 旧代码(保留)
└── incentive/ # 【业务领域】激励
├── entity/
├── repository/
├── service/
└── bo/, dao/, po/ # 旧代码(保留)
关键架构决策
1. 跨领域依赖规则
✅ 允许:其他领域 → organization (组织架构是基础领域)
❌ 禁止:平级业务领域之间直接依赖(如 attendance ↔ scrum)
// ✅ 正确示例
package info.panli.junbo.attendance.entity;
import info.panli.junbo.organization.entity.EmployeeEntity;
@Entity
public class SignRecordEntity {
@ManyToOne
private EmployeeEntity employee; // 引用组织领域
}
2. Importer 职责边界(重要)
原则: Importer 只负责数据去重,不负责业务逻辑验证
| 职责类型 | 定义 | 示例 | 处理者 |
|---|---|---|---|
| 数据去重 | 完全相同的记录 | 同员工同日期同时间的签到 | ✅ Importer |
| 业务冲突 | 逻辑上的矛盾 | 两次请假时间重叠 | ❌ Service 层 |
Importer 应该做的:
- 读取外部数据源(Excel/YAML)
- 检查记录是否完全相同(主键/唯一索引)
- 跳过重复记录,插入新记录
Importer 不应该做的:
- 业务规则验证(时间合理性、余额检查)
- 数据冲突检测(时间重叠、状态机校验)
- 复杂计算和统计
3. 数据访问层演进
| 层次 | 状态 | 使用范围 |
|---|---|---|
| Entity + Repository | ✅ 当前主力 | 数据持久化、CRUD |
| bo/dao/po | ⚠️ 遗留代码 | 旧功能、Excel 导入 |
新功能应使用 Entity + Repository,旧代码暂时保留标记 @Deprecated。
常见操作指南
编译和测试
# 编译(使用系统 JAVA_HOME)
./gradlew compileJava
# 运行测试
./gradlew test
# 构建
./gradlew build
添加新实体
- 在对应领域的
entity/创建 JPA 实体 - 在
repository/创建 Repository 接口 - 如需导入功能,在
importer/创建 ImportService - 更新
JunboApplication.java的@EnableJpaRepositories(如果是新领域)
跨领域引用
// ✅ 正确:依赖 organization
import info.panli.junbo.organization.entity.EmployeeEntity;
import info.panli.junbo.organization.repository.EmployeeRepository;
// ❌ 错误:旧的 sqlite 包(已删除)
import info.panli.junbo.sqlite.entity.EmployeeEntity;
// ❌ 错误:平级领域互相依赖
import info.panli.junbo.scrum.entity.SprintEntity; // 在 attendance 中
创建数据导入服务
@Service
@RequiredArgsConstructor
public class XxxImportService {
private final XxxRepository repository;
private final EmployeeRepository employeeRepository;
@Transactional
public ImportResult importFromExcel(String filePath) {
// 1. 读取外部数据
List<XxxBo> records = readExcel(filePath);
int inserted = 0, skipped = 0;
for (XxxBo bo : records) {
// 2. 查找员工(如果需要)
EmployeeEntity employee = employeeRepository
.findByNameOrAlias(bo.getEmployeeName())
.orElse(null);
if (employee == null) {
continue; // 找不到员工,跳过
}
// 3. 检查是否已存在(数据去重)
boolean exists = repository.existsByEmployeeAndDate(
employee, bo.getDate()
);
if (exists) {
skipped++;
continue;
}
// 4. 保存新记录
XxxEntity entity = convert(bo, employee);
repository.save(entity);
inserted++;
}
return ImportResult.builder()
.insertedCount(inserted)
.skippedCount(skipped)
.build();
}
// ❌ 不要在这里做业务逻辑验证!
}
技术细节
JPA 实体命名规范
- 实体类:
XxxEntity(如EmployeeEntity) - Repository:
XxxRepository(如EmployeeRepository) - Service:
XxxService(如KpaService) - Importer:
XxxImportService(如SignRecordImportService)
Spring Data JPA Repository 扫描
在 JunboApplication.java 中配置:
@EnableJpaRepositories(basePackages = {
"info.panli.junbo.organization.repository",
"info.panli.junbo.attendance.repository",
"info.panli.junbo.scrum.repository",
"info.panli.junbo.kpa.repository",
"info.panli.junbo.incentive.repository"
})
数据库
- 类型: SQLite
- 配置:
application.properties或application.yml - 初始化:
DataInitializer.java(自动从 YAML 导入初始数据)
项目历史变更
2026-02-06: 包结构重构
背景: 原有代码按领域组织(bo/dao/po),新增 SQLite 代码按层组织(entity/repository/controller),架构不一致。
方案: 将所有 SQLite 相关代码迁移到领域包,采用 Package by Feature 架构。
变更:
- ❌ 删除
info.panli.junbo.sqlite.*包(47 个文件) - ✅ 创建
organization/,attendance/,scrum/,kpa/,incentive/领域包 - ✅ 创建
api/,infrastructure/横切包 - ✅ 更新所有 import 语句
结果:
- ✅ 编译通过
- ✅ 96.4% 测试通过(534/554)
- ✅ 无包引用错误
常见问题
Q: 为什么 bo/dao/po 代码还在?
A: 旧功能依赖这些代码,暂时保留标记 @Deprecated,后续逐步迁移。
Q: 添加新功能应该用哪一套?
A: 使用 Entity + Repository + Service,不要再用 bo/dao/po。
Q: 如何处理跨领域的业务逻辑?
A: 通过 Service 层协调,或使用 Spring 事件机制解耦。
Q: Importer 和 Service 的边界是什么?
A: Importer 只做数据去重导入,Service 做业务逻辑验证和计算。
Q: 为什么项目使用 Java 8?
A: 项目使用 Spring Boot 2.7.18,与 Java 8 兼容性最佳。确保系统 JAVA_HOME 指向 JDK 8。
后续计划
- ✅ 包结构重构(已完成)
- ⏳ 完善 Service 层业务逻辑
- ⏳ 补充单元测试和集成测试
- ⏳ 引入 DTO 层(Controller ↔ Service)
- ⏳ 添加领域事件机制
- ⏳ 逐步移除 bo/dao/po 旧代码
参考资料
- 包结构重构设计方案
- 测试工具包使用指南
- JUnit 5 迁移完成报告
- 项目健康度报告
- 测试覆盖率报告
- 测试修复进度报告
- 测试提升总结
- 测试最终总结 ⭐ 最新
- Spring Data JPA: https://spring.io/projects/spring-data-jpa
- Package by Feature: https://phauer.com/2020/package-by-feature/
- JUnit 5: https://junit.org/junit5/docs/current/user-guide/
文档版本: 1.0 最后更新: 2026-02-06 维护者: User & Claude