组懒加载

This commit is contained in:
2026-08-28 10:20:17 +08:00
parent e027a033b4
commit afbd19522e
4 changed files with 48 additions and 29 deletions
@@ -42,6 +42,8 @@ public interface SchClassRepository extends JpaRepository<SchClass, Integer>, Jp
@Param("keyword") String keyword,
Pageable pageable);
boolean existsBySchIdAndGroupIdAndName(Integer schId, Integer groupId, String name);
boolean existsBySchIdAndGroupIdAndNameAndIdNot(Integer schId, Integer groupId, String name, Integer id);
@@ -56,6 +58,15 @@ public interface SchClassRepository extends JpaRepository<SchClass, Integer>, Jp
List<SchClass> findBySchIdAndEnrollYear(Integer schId, Integer enrollYear);
/**
* 根据学校ID和班级组ID列表查询班级
* @param schId 学校ID
* @param classIds 班级组ID列表(group_class_id,即 SchClass.classId)
* @return 匹配的班级列表(与入参顺序无关,按库内顺序返回)
*/
@Query("SELECT c FROM SchClass c WHERE c.schId = :schId AND c.classId IN :classIds")
List<SchClass> findBySchIdAndClassIds(@Param("schId") Integer schId, @Param("classIds") List<Integer> classIds);
boolean existsBySchIdAndClassId(Integer schId, Integer classId);
@Query("SELECT COUNT(c) FROM SchClass c WHERE (c.firstTeacherId IN (:ids) OR c.secondTeacherId IN (:ids)) AND c.schId = :schId AND c.graduate = 0")
@@ -23,6 +23,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@Service
@@ -77,7 +78,7 @@ public class ComSchTreeService implements IComSchTreeService {
synchronized (lock) {
baseSchsystemMap = null;
}
idToNameCache = null;
idToNameCacheBySchId.clear();
}
/**
@@ -316,38 +317,25 @@ public class ComSchTreeService implements IComSchTreeService {
public String getTeaGroupName(Integer schId, Integer id) {
BoaGroup tree = getTeaTree(schId,true);
if (tree == null) return null;
// 懒加载缓存(若树结构不变)
if (idToNameCache == null) {
idToNameCache = new HashMap<>();
buildCache(tree);
}
return idToNameCache.get(id);
if (id == null) return null;
return getTeaNameCache(schId).get(id);
}
public List<SelectIntVO> getTeaGroupNameList(Integer schId, List<Integer> ids) {
// 1. 构建缓存(如果尚未构建)
if (idToNameCache == null) {
BoaGroup tree = getTeaTree(schId,true);
if (tree == null) {
return Collections.emptyList();
}
idToNameCache = new HashMap<>();
buildCache(tree);
}
// 1. 获取当前学校的组名缓存(按 schId 懒加载,不跨学校串用)
Map<Integer, String> cache = getTeaNameCache(schId);
// 2. 如果缓存为空,直接返回空
if (idToNameCache.isEmpty()) {
if (cache.isEmpty()) {
return Collections.emptyList();
}
// 3. 处理 ids 参数
List<Integer> targetIds;
if (ids == null) {
// 如果 ids 为 null,返回全部(从缓存中取出所有 key)
targetIds = new ArrayList<>(idToNameCache.keySet());
// 如果 ids 为 null,返回全部(从当前学校缓存中取出所有 key)
targetIds = new ArrayList<>(cache.keySet());
} else {
// 过滤掉 null 的 ID,并去重(可选)
targetIds = ids.stream()
@@ -362,7 +350,7 @@ public class ComSchTreeService implements IComSchTreeService {
// 4. 根据 targetIds 构建结果列表
List<SelectIntVO> result = new ArrayList<>();
for (Integer id : targetIds) {
String name = idToNameCache.get(id);
String name = cache.get(id);
if (name != null) {
SelectIntVO vo = new SelectIntVO();
vo.setId(id);
@@ -933,14 +921,34 @@ public class ComSchTreeService implements IComSchTreeService {
}
}
private Map<Integer, String> idToNameCache;
/**
* 教师组树 id->name 缓存,按学校分桶,避免跨学校串数据
* 组树变更后需调用 clearCache() 清空(同一学校内部结构变化也会失效)
*/
private final Map<Integer, Map<Integer, String>> idToNameCacheBySchId = new ConcurrentHashMap<>();
private void buildCache(BoaGroup node) {
/**
* 获取指定学校的组名缓存(懒加载:首次按 schId 构建;树为 null 时不落缓存,下次重试)
*/
private Map<Integer, String> getTeaNameCache(Integer schId) {
Map<Integer, String> cache = idToNameCacheBySchId.get(schId);
if (cache == null) {
BoaGroup tree = getTeaTree(schId, true);
cache = new HashMap<>();
if (tree != null) {
buildCache(tree, cache);
idToNameCacheBySchId.put(schId, cache);
}
}
return cache;
}
private void buildCache(BoaGroup node, Map<Integer, String> cache) {
if (node == null) return;
idToNameCache.put(node.getId(), node.getName());
cache.put(node.getId(), node.getName());
if (node.getChildren() != null) {
for (BoaGroup child : node.getChildren()) {
buildCache(child);
buildCache(child, cache);
}
}
}
@@ -250,7 +250,7 @@ public class SchStudentLogService {
try {
LocalDateTime now = LocalDateTime.now();
// 1. 批量查询班级名称
List<SchClass> classList = schClassRepository.findAllById(affectedClassIds);
List<SchClass> classList = schClassRepository.findBySchIdAndClassIds(user.getSchId(),affectedClassIds.stream().collect(Collectors.toList()));
Map<Integer, SchClass> classMap = classList.stream()
.collect(Collectors.toMap(SchClass::getClassId, Function.identity()));
Map<Integer, String> gradeNameMap = baseSchsystemGradeService.getGradeNameMap(user.getSchId(), null, null);
@@ -330,7 +330,7 @@ public class SchStudentLogService {
// 查询原班级名称(可能跨校)
String originalClassName = "未知班级";
if (originalSchId != null && originalClassId != null) {
SchClass originalClass = schClassRepository.findByIdAndSchId(originalClassId, originalSchId).orElse(null);
SchClass originalClass = schClassRepository.findByClassIdAndSchId(originalClassId, originalSchId).orElse(null);
if (originalClass != null) {
originalClassName = gradeMap.get(originalClass.getGradeId()) + originalClass.getName();
}
@@ -139,7 +139,7 @@ public class SchStudentTransferService {
throw new DException("以下学生不存在或不属于该校: " + missing);
}
List<Integer> syncStuIds=students.stream().map(s->s.getStuId()).collect(Collectors.toList());
// List<Integer> syncStuIds=students.stream().map(s->s.getStuId()).collect(Collectors.toList());
// 收集受影响的班级ID
Set<Integer> classIds = students.stream()