kindergarten_java/docs/dev-logs/2026-03-23.md
En c436f9f384 feat: 班级名称唯一性校验
- 在 createClass 方法中添加班级名称唯一性校验
- 在 updateClass 方法中添加班级名称唯一性校验(排除当前班级)
- 使用 MyBatis-Plus 自动逻辑删除过滤
- 同一租户下已存在的班级名称抛出 INVALID_PARAMETER 异常

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 23:49:19 +08:00

167 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 开发日志 2026-03-23
## 班级名称唯一性校验
### 问题描述
当前系统中,同一个租户下可以创建多个相同名称的班级,导致数据混乱和管理困难。
### 需求
在新增和修改班级时,需要校验班级名称在同一租户下的唯一性。
### 实现方案
#### 1. 修改文件
| 文件 | 修改内容 |
|------|----------|
| `reading-platform-java/src/main/java/com/reading/platform/service/impl/ClassServiceImpl.java` | 在 `createClass``updateClass` 方法中添加唯一性校验 |
#### 2. 代码修改
**创建班级时校验**`createClass` 方法):
```java
// 检查班级名称是否唯一MyBatis-Plus 会自动排除 deleted=1 的记录)
LambdaQueryWrapper<Clazz> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Clazz::getTenantId, tenantId)
.eq(Clazz::getName, request.getName());
Long count = clazzMapper.selectCount(wrapper);
if (count > 0) {
throw new BusinessException(ErrorCode.INVALID_PARAM, "该班级名称已存在");
}
```
**更新班级时校验**`updateClass` 方法):
```java
if (StringUtils.hasText(request.getName())) {
// 检查班级名称是否唯一(排除当前班级和已删除)
LambdaQueryWrapper<Clazz> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Clazz::getTenantId, clazz.getTenantId())
.eq(Clazz::getName, request.getName())
.ne(Clazz::getId, id); // 排除当前班级
Long count = clazzMapper.selectCount(wrapper);
if (count > 0) {
throw new BusinessException(ErrorCode.INVALID_PARAM, "该班级名称已存在");
}
clazz.setName(request.getName());
}
```
### 技术要点
1. **逻辑删除处理**: `Clazz` 实体继承 `BaseEntity`,包含 `deleted` 字段MyBatis-Plus 的 `@TableLogic` 注解会在查询时自动添加 `deleted = 0` 条件
2. **唯一性校验范围**: 仅检查同一租户下的未删除记录
3. **错误提示**: 统一返回 "该班级名称已存在"
4. **错误码**: 使用 `ErrorCode.INVALID_PARAMETER`(参数校验错误,错误码 2004
### 测试场景
- [x] 创建班级 "小一班" → 成功
- [x] 再次创建班级 "小一班"(同租户) → 应抛出异常 "该班级名称已存在"
- [x] 删除 "小一班" 后,再次创建 "小一班" → 成功(因为原记录已删除)
- [x] 更新班级,将名称改为已存在的名称 → 应抛出异常
- [x] 更新班级,名称不变 → 成功
- [x] 后端编译通过
### 文件变更列表
| 文件 | 变更说明 |
|------|---------|
| `reading-platform-java/src/main/java/com/reading/platform/service/impl/ClassServiceImpl.java` | 在 `createClass``updateClass` 方法中添加唯一性校验逻辑 |
---
**今日完成**: 班级名称唯一性校验、教师手机号唯一性校验
---
## 教师手机号唯一性校验
### 问题描述
在学校端教师管理中,新增和编辑教师时未对手机号唯一性进行校验,导致同一租户下不同教师可能使用相同的手机号。
### 需求
- **新增教师**:检查手机号在当前租户下是否已存在
- **编辑教师**:检查手机号是否与当前租户下其他教师重复(排除自己)
### 实现方案
#### 修改文件
| 文件 | 修改内容 |
|------|----------|
| `TeacherServiceImpl.java` | 添加 `checkPhoneUnique` 方法,在 `createTeacher``updateTeacher` 中调用 |
#### 代码修改
**新增手机号校验方法**
```java
/**
* 检查手机号唯一性
*/
private void checkPhoneUnique(Long tenantId, String phone, Long excludeTeacherId) {
if (!StringUtils.hasText(phone)) {
return; // 手机号为空时不校验(由 @NotBlank 校验)
}
LambdaQueryWrapper<Teacher> wrapper = new LambdaQueryWrapper<Teacher>()
.eq(Teacher::getTenantId, tenantId)
.eq(Teacher::getPhone, phone);
// 编辑时排除当前教师
if (excludeTeacherId != null) {
wrapper.ne(Teacher::getId, excludeTeacherId);
}
Teacher existing = teacherMapper.selectOne(wrapper);
if (existing != null) {
log.warn("手机号已存在tenantId: {}, phone: {}", tenantId, phone);
throw new BusinessException(ErrorCode.DATA_ALREADY_EXISTS, "手机号已存在");
}
}
```
**createTeacher 方法**:在插入前调用校验
```java
// 检查手机号是否已存在
checkPhoneUnique(tenantId, request.getPhone(), null);
```
**updateTeacher 方法**:在更新前调用校验(排除当前教师)
```java
// 检查手机号是否已存在(排除当前教师)
checkPhoneUnique(teacher.getTenantId(), request.getPhone(), teacher.getId());
```
### 技术要点
1. **租户隔离**:校验时带上 `tenantId` 条件,确保不同租户之间数据隔离
2. **编辑排除逻辑**:使用 `ne` 条件排除当前教师 ID避免自己修改自己时报错
3. **空值处理**:手机号为空时不校验(由 Controller 层的 `@NotBlank` 注解校验)
4. **错误码**:使用 `ErrorCode.DATA_ALREADY_EXISTS`(数据已存在)
### 测试场景
- [x] 创建教师使用手机号 13800138000 → 成功
- [x] 再次创建教师使用相同手机号 13800138000同租户 → 应失败,提示"手机号已存在"
- [x] 创建教师使用不同手机号 13800138001 → 成功
- [x] 编辑教师 A不修改手机号 → 成功
- [x] 编辑教师 A修改为教师 B 的手机号 → 应失败
- [x] 编辑教师 A修改为未使用的手机号 → 成功
- [x] 租户 1 下已有手机号 13800138000租户 2 下可以使用相同手机号 → 成功(租户隔离)
- [x] 后端编译通过
### 文件变更列表
| 文件 | 变更说明 |
|------|---------|
| `reading-platform-java/src/main/java/com/reading/platform/service/impl/TeacherServiceImpl.java` | 添加 `checkPhoneUnique` 方法,在 `createTeacher``updateTeacher` 中调用 |功能