@@ -0,0 +1,40 @@
|
|||||||
|
package com.yunhai.bschclassmanage.model.vo.sch;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
|
||||||
|
import com.yunhai.bschclassmanage.model.vo.SelectStrVO;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 教师分组信息(oapi/sch/getTeaCustomGroupList 输出,对应教师分组管理页面的组/组员/组长三栏)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class OapiGroupVO {
|
||||||
|
|
||||||
|
/** 组ID(sch_teacher_custom_group.id) */
|
||||||
|
private Integer groupId;
|
||||||
|
|
||||||
|
/** 组名称 */
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
/** 组类型(1年级组 2教研组 3备课组) */
|
||||||
|
private Integer groupType;
|
||||||
|
|
||||||
|
/** 组类型名称 */
|
||||||
|
private String groupTypeName;
|
||||||
|
|
||||||
|
/** 学科集合 [{id:学科编码, name:学科名称}] */
|
||||||
|
private List<SelectStrVO> subjects;
|
||||||
|
|
||||||
|
/** 年级集合 [{id:年级编码, name:年级名称}] */
|
||||||
|
private List<SelectIntVO> grades;
|
||||||
|
|
||||||
|
/** 组员集合 [{id:教师id, name:教师名称}](不含组长) */
|
||||||
|
private List<SelectIntVO> members;
|
||||||
|
|
||||||
|
/** 组长集合 [{id:教师id, name:教师名称}] */
|
||||||
|
private List<SelectIntVO> leaders;
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.yunhai.bschclassmanage;
|
||||||
|
|
||||||
|
import com.yunhai.bschclassmanage.service.IStudentClassHistoryService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地复现 api/history/getHistoryClassTeachByStuId?stuId=10068 的内部服务错误。
|
||||||
|
* 直接调用 service 层(绕过 SSO 过滤器),打印真实异常堆栈。
|
||||||
|
*/
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
|
||||||
|
class ReproduceHistoryTeachByStuIdTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IStudentClassHistoryService studentClassHistoryService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reproduce() {
|
||||||
|
try {
|
||||||
|
// 模拟真实 HTTP 场景:UserContextInterceptor.resolveUser 恒返回 null,schId 为 null
|
||||||
|
Object result = studentClassHistoryService.getHistoryClassTeachByStuId(null, 10068);
|
||||||
|
System.out.println("=== SUCCESS (schId=null) ===");
|
||||||
|
System.out.println(result);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.out.println("=== EXCEPTION (schId=null): " + e.getClass().getName() + " ===");
|
||||||
|
System.out.println("message: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private com.yunhai.bschclassmanage.utils.RedisUtil redisUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private com.yunhai.bschclassmanage.Repository.SchStudentRepository schStudentRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回归用例:同一 stu_id 在 sch_student 存在多行(学生在多所学校各有一条就学记录)。
|
||||||
|
* 修复前 findByStuId 返回 Optional,会抛 NonUniqueResultException(线上表现为 code 6 内部服务错误)。
|
||||||
|
* 修复后应取当前学校那一行正常返回。@Transactional 保证测试数据回滚。
|
||||||
|
*/
|
||||||
|
@org.springframework.transaction.annotation.Transactional
|
||||||
|
@Test
|
||||||
|
void duplicateStuIdShouldNotCrash() {
|
||||||
|
// 本地库里 stu_id=10068 已有一行(sch_id=3, class_id=298),再造一行别校的记录
|
||||||
|
com.yunhai.bschclassmanage.entity.SchStudent other = new com.yunhai.bschclassmanage.entity.SchStudent();
|
||||||
|
other.setStuId(10068);
|
||||||
|
other.setSchId(999);
|
||||||
|
other.setClassId(888);
|
||||||
|
other.setName("重复记录-别校");
|
||||||
|
schStudentRepository.save(other);
|
||||||
|
schStudentRepository.flush();
|
||||||
|
|
||||||
|
// 当前学校 schId=3 的记录应被正确选中,不再抛 NonUniqueResultException
|
||||||
|
Object result = studentClassHistoryService.getHistoryClassTeachByStuId(3, 10068);
|
||||||
|
System.out.println("=== DUPLICATE stu_id RESULT ===");
|
||||||
|
System.out.println(result);
|
||||||
|
if (result == null) {
|
||||||
|
throw new AssertionError("expected non-null result");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 换成重复行所在学校 schId=999:实时表命中但班级不存在 → 应返回业务异常而不是内部错误
|
||||||
|
try {
|
||||||
|
studentClassHistoryService.getHistoryClassTeachByStuId(999, 10068);
|
||||||
|
System.out.println("=== schId=999 unexpectedly succeeded ===");
|
||||||
|
} catch (com.yunhai.platform.utils.exception.DException e) {
|
||||||
|
System.out.println("=== schId=999 DException (expected): " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void poisonCacheRead() {
|
||||||
|
for (String key : new String[]{
|
||||||
|
"bsch.classmanage.system_yearterm_poison",
|
||||||
|
"bsch.classmanage.system_yearterm_poison2"}) {
|
||||||
|
try {
|
||||||
|
Object raw = redisUtil.get(key, Object.class);
|
||||||
|
System.out.println("=== RAW GET [" + key + "]: " + (raw == null ? "null" : raw.getClass().getName()));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.out.println("=== RAW GET EXCEPTION [" + key + "]: " + e.getClass().getName() + " ===");
|
||||||
|
System.out.println("message: " + e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Object list = redisUtil.getList(key, com.yunhai.bschclassmanage.entity.BaseYearTerm.class);
|
||||||
|
System.out.println("=== GET LIST [" + key + "]: " + list);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.out.println("=== GET LIST EXCEPTION [" + key + "]: " + e.getClass().getName() + " ===");
|
||||||
|
System.out.println("message: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void reproduceWithSchId() {
|
||||||
|
try {
|
||||||
|
Object result = studentClassHistoryService.getHistoryClassTeachByStuId(3, 10068);
|
||||||
|
System.out.println("=== SUCCESS (schId=3) ===");
|
||||||
|
System.out.println(result);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.out.println("=== EXCEPTION (schId=3): " + e.getClass().getName() + " ===");
|
||||||
|
System.out.println("message: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user