1
This commit is contained in:
@@ -47,6 +47,12 @@
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 显式引入 JDBC(提供 JdbcTemplate,用于 backupAllSnapshot 的批量快照插入) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Nacos 配置中心(替代 Spring Cloud Config)。Spring Cloud Alibaba 2021.0.5 适配 Boot 2.7 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchClass;
|
||||
import com.yunhai.bschclassmanage.entity.SchClassHistory;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchClass;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -66,4 +68,29 @@ public interface SchClassRepository extends JpaRepository<SchClass, Integer>, Jp
|
||||
*/
|
||||
@Query("SELECT MIN(c.enrollYear) FROM SchClass c WHERE c.schId = :schId AND c.gradeId IN :gradeIds")
|
||||
Integer findMinEnrollYear(@Param("schId") Integer schId, @Param("gradeIds") List<Integer> gradeIds);
|
||||
|
||||
/**
|
||||
* 学年升级:指定学校下、给定年级(非最高年级)的未毕业班级整体升一级
|
||||
* 使用 grade_id = grade_id + 1 的 SET 语义,单次语句原子完成,避免逐班加载与保存
|
||||
* @param schId 学校ID(安全过滤)
|
||||
* @param gradeIds 需要升级的年级ID列表(非最高年级)
|
||||
* @param now 修改时间
|
||||
* @return 实际受影响行数
|
||||
*/
|
||||
@Modifying(clearAutomatically = true)
|
||||
@Query("UPDATE SchClass c SET c.gradeId = c.gradeId + 1, c.updateDate = :now, c.updateUserId = 0 " +
|
||||
"WHERE c.schId = :schId AND c.gradeId IN :gradeIds AND c.graduate = false")
|
||||
int batchUpgradeGrade(@Param("schId") Integer schId, @Param("gradeIds") List<Integer> gradeIds, @Param("now") Date now);
|
||||
|
||||
/**
|
||||
* 学年升级:指定学校下、最高年级的未毕业班级标记为毕业
|
||||
* @param schId 学校ID(安全过滤)
|
||||
* @param maxGrade 最高年级ID
|
||||
* @param now 修改时间
|
||||
* @return 实际受影响行数
|
||||
*/
|
||||
@Modifying(clearAutomatically = true)
|
||||
@Query("UPDATE SchClass c SET c.graduate = true, c.updateDate = :now, c.updateUserId = 0 " +
|
||||
"WHERE c.schId = :schId AND c.gradeId = :maxGrade AND c.graduate = false")
|
||||
int batchGraduate(@Param("schId") Integer schId, @Param("maxGrade") Integer maxGrade, @Param("now") Date now);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchDicCampus;
|
||||
import com.yunhai.bschclassmanage.entity.SchDicCourse;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchDicMajors;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchStudent;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.yunhai.bschclassmanage.Repository;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.SchTeacher;
|
||||
import com.yunhai.bschclassmanage.model.vo.TeacherSchVO;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync // 启用异步处理
|
||||
@@ -21,4 +22,17 @@ public class AsyncConfig {
|
||||
executor.initialize(); // 初始化
|
||||
return executor;
|
||||
}
|
||||
|
||||
/** 新增:审计日志异步池(独立,避免与业务日志互相挤压;量大所以池更大) */
|
||||
@Bean(name = "auditLogExecutor")
|
||||
public Executor auditLogExecutor() {
|
||||
ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor();
|
||||
ex.setCorePoolSize(4);
|
||||
ex.setMaxPoolSize(16);
|
||||
ex.setQueueCapacity(2000);
|
||||
ex.setThreadNamePrefix("audit-log-");
|
||||
ex.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); // 队列满丢弃,不拖垮主流程
|
||||
ex.initialize();
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.yunhai.bschclassmanage.utils.UserContext;
|
||||
import com.yunhai.bschclassmanage.config.Config;
|
||||
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
|
||||
import com.yunhai.platform.utils.model.BoaModule;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -27,8 +28,8 @@ public class UserController {
|
||||
}
|
||||
|
||||
@GetMapping("getUserInfo")
|
||||
public UserContext.UserInfo getUserInfo() {
|
||||
return UserContext.getCurrentUser();
|
||||
public BoaUser getUserInfo(BoaUser authUserWithDept) {
|
||||
return authUserWithDept;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -2,6 +2,7 @@ package com.yunhai.bschclassmanage.controller.oapi.sync;
|
||||
|
||||
import com.yunhai.bschclassmanage.config.Config;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncGroupDTO;
|
||||
import com.yunhai.bschclassmanage.service.ISyncGroupService;
|
||||
import com.yunhai.bschclassmanage.utils.OtherUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -23,14 +24,14 @@ public class SyncGroupController {
|
||||
public void AddGroup(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
//判断 2,"学校组" 4, "班级组"
|
||||
BaseGroup group = OtherUtil.jsonParseObject(jsonString, BaseGroup.class);
|
||||
SyncGroupDTO group = OtherUtil.jsonParseObject(jsonString, SyncGroupDTO.class);
|
||||
syncGroupService.syncAddOrUpdate(group);
|
||||
}
|
||||
|
||||
@PostMapping("UpdateGroup")
|
||||
public void UpdateGroup(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
BaseGroup group = OtherUtil.jsonParseObject(jsonString, BaseGroup.class);
|
||||
SyncGroupDTO group = OtherUtil.jsonParseObject(jsonString, SyncGroupDTO.class);
|
||||
syncGroupService.syncAddOrUpdate(group);
|
||||
}
|
||||
|
||||
@@ -38,6 +39,7 @@ public class SyncGroupController {
|
||||
public void DeleteGroup(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
}
|
||||
|
||||
@PostMapping("SyncGroup")
|
||||
public void SyncGroup(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
|
||||
+3
-8
@@ -1,12 +1,9 @@
|
||||
package com.yunhai.bschclassmanage.controller.oapi.sync;
|
||||
|
||||
import com.yunhai.bschclassmanage.config.Config;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseUser;
|
||||
import com.yunhai.bschclassmanage.model.tool.DeleteUser;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncUserDTO;
|
||||
import com.yunhai.bschclassmanage.service.ISyncUserService;
|
||||
import com.yunhai.bschclassmanage.service.impl.sync.SyncGroupService;
|
||||
import com.yunhai.bschclassmanage.service.impl.sync.SyncUserService;
|
||||
import com.yunhai.bschclassmanage.utils.OtherUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -25,14 +22,14 @@ public class SyncUserController {
|
||||
@PostMapping("AddUser")
|
||||
public void AddUser(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
List<BaseUser> userlist = OtherUtil.jsonParseList(jsonString, BaseUser.class);
|
||||
List<SyncUserDTO> userlist = OtherUtil.jsonParseList(jsonString, SyncUserDTO.class);
|
||||
syncUserService.syncAddOrUpdate(userlist);
|
||||
}
|
||||
|
||||
@PostMapping("UpdateUser")
|
||||
public void UpdateUser(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
List<BaseUser> userList = OtherUtil.jsonParseList(jsonString, BaseUser.class);
|
||||
List<SyncUserDTO> userList = OtherUtil.jsonParseList(jsonString, SyncUserDTO.class);
|
||||
syncUserService.syncAddOrUpdate(userList);
|
||||
}
|
||||
|
||||
@@ -46,7 +43,5 @@ public class SyncUserController {
|
||||
@PostMapping("SyncUser")
|
||||
public void SyncUser(@RequestBody String jsonString) {
|
||||
log.info("jsonString="+jsonString);
|
||||
List<DeleteUser> deleteUserList= OtherUtil.jsonParseList(jsonString, DeleteUser.class);
|
||||
syncUserService.deleteUser(deleteUserList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.yunhai.bschclassmanage.model.tool;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class BaseUser {
|
||||
private int id;
|
||||
private Integer[] tags;
|
||||
private String phone;
|
||||
private String profilePicture;
|
||||
private LocalDateTime birth;
|
||||
private Integer[] depts;
|
||||
private Integer status;
|
||||
private String idcard;
|
||||
private Integer type;
|
||||
private String email;
|
||||
private String name;
|
||||
private String account;
|
||||
private Integer gender;
|
||||
private List<GroupInfo> groups;
|
||||
private List<RoleInfo> roleList;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class GroupInfo {
|
||||
private Integer groupId;
|
||||
private Integer no;
|
||||
private Integer schoolId;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class RoleInfo {
|
||||
private Integer roleId;
|
||||
private Integer schId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yunhai.bschclassmanage.model.tool;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SyncGroupDTO {
|
||||
private Integer id;
|
||||
private String code;
|
||||
private String name;
|
||||
private Integer type;
|
||||
private Integer pid;
|
||||
private Integer no;
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.yunhai.bschclassmanage.service;
|
||||
|
||||
import com.yunhai.bschclassmanage.entity.BaseDicGrade;
|
||||
import com.yunhai.bschclassmanage.enums.NodeType;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncGroupDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,7 +8,7 @@ import java.util.List;
|
||||
@Service
|
||||
public interface ISyncGroupService {
|
||||
|
||||
void syncAddOrUpdate(BaseGroup group);
|
||||
void addOrUpdateSchool(BaseGroup group);
|
||||
void syncAddOrUpdate(SyncGroupDTO group);
|
||||
void addOrUpdateSchool(SyncGroupDTO group);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.yunhai.bschclassmanage.service;
|
||||
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseUser;
|
||||
import com.yunhai.bschclassmanage.model.tool.DeleteUser;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncUserDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,7 +9,7 @@ import java.util.List;
|
||||
@Service
|
||||
public interface ISyncUserService {
|
||||
|
||||
void syncAddOrUpdate(List<BaseUser> userList);
|
||||
void syncAddOrUpdate(List<SyncUserDTO> userList);
|
||||
|
||||
void deleteUser(List<DeleteUser> deleteUserList);
|
||||
}
|
||||
|
||||
+44
-66
@@ -5,119 +5,98 @@ import com.yunhai.bschclassmanage.entity.*;
|
||||
import com.yunhai.bschclassmanage.enums.SchType;
|
||||
import com.yunhai.bschclassmanage.model.tool.YearTerm;
|
||||
import com.yunhai.bschclassmanage.service.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SchClassUpgradeService {
|
||||
|
||||
@Autowired
|
||||
private SchClassCacheService schClassCacheService;
|
||||
|
||||
@Autowired
|
||||
private SchClassQueryService queryService;
|
||||
|
||||
@Autowired
|
||||
private SchClassRepository schClassRepository;
|
||||
|
||||
@Autowired
|
||||
private ISchBinSchsystemService schBinSchsystemService;
|
||||
|
||||
@Autowired
|
||||
private IBaseSchsystemGradeService baseSchsystemGradeService;
|
||||
|
||||
@Autowired
|
||||
private IBaseYearTermService baseYearTermService;
|
||||
|
||||
@Autowired
|
||||
private UpgradeLogRepository upgradeLogRepository;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
private final SchClassCacheService schClassCacheService;
|
||||
private final SchClassRepository schClassRepository;
|
||||
private final ISchBinSchsystemService schBinSchsystemService;
|
||||
private final IBaseSchsystemGradeService baseSchsystemGradeService;
|
||||
private final IBaseYearTermService baseYearTermService;
|
||||
private final UpgradeLogRepository upgradeLogRepository;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
|
||||
public void upgradeAllClasses() {
|
||||
Date now = new Date();
|
||||
// 获取当前学年学期
|
||||
YearTerm yearTerm = baseYearTermService.getCurrentYearTerm();
|
||||
if (yearTerm == null) {
|
||||
log.error("当前学年学期未配置,升级中止");
|
||||
return;
|
||||
}
|
||||
int currentYear = yearTerm.getYear();
|
||||
|
||||
List<Integer> schoolIds = schBinSchsystemService.getSchIds();
|
||||
|
||||
for (Integer schId : schoolIds) {
|
||||
// ----- 2. 获取该校所有学制 -----
|
||||
List<Integer> schsystemIds = schBinSchsystemService.getSchBinSchsystemIds(schId);
|
||||
// 学校类型在整个学校维度内不变,提升到学制循环外只查一次
|
||||
Integer schType = schBinSchsystemService.getSchType(schId);
|
||||
|
||||
// ----- 获取该校所有学制 -----
|
||||
List<Integer> schsystemIds = schBinSchsystemService.getSchBinSchsystemIds(schId);
|
||||
for (Integer sysId : schsystemIds) {
|
||||
Boolean status=true;
|
||||
if (upgradeLogRepository.existsBySchIdAndSysIdAndYearAndStatus(schId, sysId, currentYear,status)) {
|
||||
log.info("学校{}学制{}学年{}学期已升级,跳过", schId, sysId, currentYear);
|
||||
continue; // 直接返回,不做任何操作
|
||||
// 已成功升级过的(学年+学制)直接跳过,避免重复升级
|
||||
if (upgradeLogRepository.existsBySchIdAndSysIdAndYearAndStatus(schId, sysId, currentYear, true)) {
|
||||
log.info("学校{}学制{}学年{}已成功升级,跳过", schId, sysId, currentYear);
|
||||
continue;
|
||||
}
|
||||
boolean success = true;
|
||||
try {
|
||||
upgradeSingleSystem(schId, schType, sysId, now);
|
||||
log.info("学校{} 学制{} 学年{} 升级执行成功", schId, sysId, currentYear);
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
log.error("学校{}学制{}升级失败,已跳过,不影响其他学制", schId, sysId, e);
|
||||
status=false;
|
||||
}
|
||||
upgradeLogRepository.save(new UpgradeLog(schId, sysId, currentYear,now,status));
|
||||
// 无论成功失败都落升级日志,失败记录便于下次重试(existsBy...Status=true 不命中即可重跑)
|
||||
try {
|
||||
upgradeLogRepository.save(new UpgradeLog(schId, sysId, currentYear, now, success));
|
||||
} catch (Exception e) {
|
||||
log.error("学校{}学制{}升级结果日志写入失败", schId, sysId, e);
|
||||
}
|
||||
// 清除该校缓存
|
||||
}
|
||||
// 升级完成后清除该校班级缓存(含毕业缓存),避免脏数据
|
||||
schClassCacheService.clearClassCache(schId);
|
||||
schClassCacheService.clearGradeateClassCache(schId);
|
||||
}
|
||||
}
|
||||
|
||||
//升级业务逻辑
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
protected void upgradeSingleSystem(Integer schId, Integer schType, Integer sysId, Date now) {
|
||||
// 1. 检查是否已升级(利用数据库唯一索引防并发)
|
||||
// 2. 执行升级逻辑
|
||||
// 3. 插入升级日志
|
||||
|
||||
// 1. 获取该学制下的年级定义(轻量、带缓存),得到年级集合与最高年级
|
||||
Map<Integer, String> gradeMap = baseSchsystemGradeService.getGradeNameMap(schId, sysId, null);
|
||||
if (gradeMap == null || gradeMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<Integer> gradeIds = new ArrayList<>(gradeMap.keySet());
|
||||
Collections.sort(gradeIds);
|
||||
if (gradeIds.isEmpty()) return;
|
||||
|
||||
Integer maxGrade = gradeIds.get(gradeIds.size() - 1);
|
||||
|
||||
// ----- 3. 升级非最高年级 -----
|
||||
for (Integer gradeId : gradeIds) {
|
||||
if (gradeId.equals(maxGrade)) continue;
|
||||
List<SchClass> classList = queryService.getSchClassCacheFilter(schId, gradeId, null);
|
||||
if (classList.isEmpty()) continue;
|
||||
|
||||
// 执行升级
|
||||
for (SchClass clazz : classList) {
|
||||
if(schType.equals(SchType.BASICEDUCATION.getKey())) {
|
||||
clazz.setGradeId(gradeId + 1);//基础教育年级+1
|
||||
// 2. 非最高年级:基础教育整体升一级(SET 语义,单语句原子完成)
|
||||
if (SchType.BASICEDUCATION.getKey().equals(schType)) {
|
||||
List<Integer> nonMaxGrades = new ArrayList<>(gradeIds.subList(0, gradeIds.size() - 1));
|
||||
if (!nonMaxGrades.isEmpty()) {
|
||||
int updated = schClassRepository.batchUpgradeGrade(schId, nonMaxGrades, now);
|
||||
log.info("学校{}学制{} 非最高年级升一级,影响班级数={}", schId, sysId, updated);
|
||||
}
|
||||
clazz.setUpdateDate(now);
|
||||
clazz.setUpdateUserId(0);
|
||||
}
|
||||
schClassRepository.saveAll(classList);
|
||||
}
|
||||
|
||||
// ----- 4. 处理最高年级(毕业) -----
|
||||
List<SchClass> graduateClassList = queryService.getSchClassCacheFilter(schId, maxGrade, null);
|
||||
if (!graduateClassList.isEmpty()) {
|
||||
for (SchClass clazz : graduateClassList) {
|
||||
clazz.setGraduate(true);
|
||||
clazz.setUpdateDate(now);
|
||||
clazz.setUpdateUserId(0);
|
||||
}
|
||||
schClassRepository.saveAll(graduateClassList);
|
||||
}
|
||||
|
||||
// 3. 最高年级:毕业
|
||||
int graduated = schClassRepository.batchGraduate(schId, maxGrade, now);
|
||||
log.info("学校{}学制{} 最高年级(年级ID={})毕业,影响班级数={}", schId, sysId, maxGrade, graduated);
|
||||
}
|
||||
|
||||
|
||||
@@ -151,5 +130,4 @@ public class SchClassUpgradeService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.yunhai.bschclassmanage.Repository.SchInfoRepository;
|
||||
import com.yunhai.bschclassmanage.entity.SchInfo;
|
||||
import com.yunhai.bschclassmanage.enums.NodeType;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncGroupDTO;
|
||||
import com.yunhai.bschclassmanage.service.ISyncGroupService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -19,7 +20,7 @@ public class SyncGroupService implements ISyncGroupService {
|
||||
private SchInfoRepository schInfoRepository;
|
||||
|
||||
|
||||
public void syncAddOrUpdate(BaseGroup group) {
|
||||
public void syncAddOrUpdate(SyncGroupDTO group) {
|
||||
|
||||
//学校组 年级组 班级组
|
||||
if(group.getType().equals(NodeType.SCHOOL.getId())){
|
||||
@@ -37,7 +38,7 @@ public class SyncGroupService implements ISyncGroupService {
|
||||
}
|
||||
|
||||
|
||||
public void addOrUpdateSchool(BaseGroup group)
|
||||
public void addOrUpdateSchool(SyncGroupDTO group)
|
||||
{
|
||||
Optional<SchInfo> schOpt=schInfoRepository.findBySchId(group.getId());
|
||||
if(schOpt.isPresent()){
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
package com.yunhai.bschclassmanage.service.impl.sync;
|
||||
|
||||
import com.yunhai.bschclassmanage.Repository.SchInfoRepository;
|
||||
import com.yunhai.bschclassmanage.Repository.SchStudentRepository;
|
||||
import com.yunhai.bschclassmanage.Repository.SchTeacherGroupRepository;
|
||||
import com.yunhai.bschclassmanage.Repository.SchTeacherRepository;
|
||||
import com.yunhai.bschclassmanage.entity.SchInfo;
|
||||
import com.yunhai.bschclassmanage.entity.SchStudent;
|
||||
import com.yunhai.bschclassmanage.entity.SchTeacher;
|
||||
import com.yunhai.bschclassmanage.entity.SchTeacherGroup;
|
||||
import com.yunhai.bschclassmanage.enums.NodeType;
|
||||
import com.yunhai.bschclassmanage.enums.StuAbnormalStatus;
|
||||
import com.yunhai.bschclassmanage.enums.TransferStatus;
|
||||
import com.yunhai.bschclassmanage.enums.UserRole;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseGroup;
|
||||
import com.yunhai.bschclassmanage.model.tool.BaseUser;
|
||||
import com.yunhai.bschclassmanage.model.tool.DeleteUser;
|
||||
import com.yunhai.bschclassmanage.service.ISchTeacherService;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncUserDTO;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncUserGroupDTO;
|
||||
import com.yunhai.bschclassmanage.model.tool.SyncUserRoleDTO;
|
||||
import com.yunhai.bschclassmanage.service.ISyncUserService;
|
||||
import com.yunhai.bschclassmanage.service.impl.student.SchStudentCacheService;
|
||||
import com.yunhai.bschclassmanage.service.impl.teacher.SchTeacherCacheService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SyncUserService implements ISyncUserService {
|
||||
|
||||
@@ -47,18 +45,25 @@ public class SyncUserService implements ISyncUserService {
|
||||
private SchTeacherCacheService schTeacherCacheService;
|
||||
|
||||
// ==================== 同步入口 ====================
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncAddOrUpdate(List<BaseUser> userList) {
|
||||
public void syncAddOrUpdate(List<SyncUserDTO> userList) {
|
||||
if (userList == null || userList.isEmpty()) return;
|
||||
|
||||
// 按角色分组
|
||||
List<BaseUser> syncStudentList = new ArrayList<>();
|
||||
List<BaseUser> syncTeacherList = new ArrayList<>();
|
||||
// 按角色分组(每个用户只遍历一次 roleList)
|
||||
List<SyncUserDTO> syncStudentList = new ArrayList<>();
|
||||
List<SyncUserDTO> syncTeacherList = new ArrayList<>();
|
||||
|
||||
for (BaseUser user : userList) {
|
||||
if (isStudent(user)) syncStudentList.add(user);
|
||||
if (isTeacher(user)) syncTeacherList.add(user);
|
||||
for (SyncUserDTO user : userList) {
|
||||
Set<Integer> roleIds = collectRoleIds(user);
|
||||
if (isStudent(roleIds)) {
|
||||
syncStudentList.add(user);
|
||||
} else if (isTeacher(roleIds)) {
|
||||
syncTeacherList.add(user);
|
||||
} else {
|
||||
log.error("用户:{} 角色不符合同步要求!", user.getAccount());
|
||||
}
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
@@ -71,124 +76,112 @@ public class SyncUserService implements ISyncUserService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteUser(List<DeleteUser> deleteUserList) {
|
||||
if (deleteUserList == null || deleteUserList.isEmpty()) return;
|
||||
|
||||
// 提取所有 userId
|
||||
List<Integer> allUserIds = deleteUserList.stream()
|
||||
.map(DeleteUser::getUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (allUserIds.isEmpty()) return;
|
||||
|
||||
// ---------- 1. 物理删除学生 ----------
|
||||
List<DeleteUser> studentDeletes = deleteUserList.stream()
|
||||
// 过滤出有效的 (userId, groupId) 条目,仅计算一次
|
||||
List<DeleteUser> validDeletes = deleteUserList.stream()
|
||||
.filter(du -> du.getUserId() != null && du.getGroupId() != null)
|
||||
.collect(Collectors.toList());
|
||||
if (!studentDeletes.isEmpty()) {
|
||||
// 批量查询学生
|
||||
List<SchStudent> allStudents = schStudentRepository.findByStuIdIn(allUserIds);
|
||||
Map<String, SchStudent> studentMap = allStudents.stream()
|
||||
if (validDeletes.isEmpty()) return;
|
||||
|
||||
List<Integer> allUserIds = validDeletes.stream()
|
||||
.map(DeleteUser::getUserId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// ---------- 1. 物理删除学生 ----------
|
||||
List<SchStudent> toDeleteStudents = new ArrayList<>();
|
||||
Map<String, SchStudent> studentMap = schStudentRepository.findByStuIdIn(allUserIds).stream()
|
||||
.collect(Collectors.toMap(
|
||||
s -> buildStudentKey(s.getStuId(), s.getGroupId()),
|
||||
Function.identity()
|
||||
));
|
||||
List<SchStudent> toDelete = new ArrayList<>();
|
||||
for (DeleteUser du : studentDeletes) {
|
||||
String key = buildStudentKey(du.getUserId(), du.getGroupId());
|
||||
SchStudent stu = studentMap.get(key);
|
||||
for (DeleteUser du : validDeletes) {
|
||||
SchStudent stu = studentMap.get(buildStudentKey(du.getUserId(), du.getGroupId()));
|
||||
if (stu != null) {
|
||||
toDelete.add(stu);
|
||||
toDeleteStudents.add(stu);
|
||||
}
|
||||
}
|
||||
if (!toDelete.isEmpty()) {
|
||||
// 先清除缓存(需要 schId,可从学生实体获取或查询)
|
||||
for (SchStudent stu : toDelete) {
|
||||
// 假设 SchStudent 有 schId 字段,若没有则需通过 groupId 查询
|
||||
Integer schId = stu.getSchId(); // 若没有,调用 service 查询
|
||||
if (schId != null) {
|
||||
schStudentCacheService.clearClassStudentCache(schId, stu.getGroupId());
|
||||
if (!toDeleteStudents.isEmpty()) {
|
||||
// 按 (schId, classId) 去重后清除缓存
|
||||
Map<Integer, Set<Integer>> classKeys = new HashMap<>();
|
||||
for (SchStudent stu : toDeleteStudents) {
|
||||
if (stu.getSchId() != null && stu.getGroupId() != null) {
|
||||
classKeys.computeIfAbsent(stu.getSchId(), k -> new HashSet<>()).add(stu.getGroupId());
|
||||
}
|
||||
}
|
||||
// 物理删除
|
||||
schStudentRepository.deleteAll(toDelete);
|
||||
}
|
||||
classKeys.forEach((schId, classIds) -> schStudentCacheService.clearClassStudentCaches(schId, classIds));
|
||||
schStudentRepository.deleteAll(toDeleteStudents);
|
||||
}
|
||||
|
||||
// ---------- 2. 物理删除教师分组(不删教师主体) ----------
|
||||
List<DeleteUser> teacherDeletes = deleteUserList.stream()
|
||||
.filter(du -> du.getUserId() != null && du.getGroupId() != null)
|
||||
.collect(Collectors.toList());
|
||||
if (!teacherDeletes.isEmpty()) {
|
||||
// 查询所有涉及的分组
|
||||
List<SchTeacherGroup> allGroups = schTeacherGroupRepository.findByTeaIdIn(allUserIds);
|
||||
Map<String, SchTeacherGroup> groupMap = allGroups.stream()
|
||||
.collect(Collectors.toMap(
|
||||
g -> buildTeacherGroupKey(g.getTeaId(), g.getGroupId()),
|
||||
Function.identity()
|
||||
));
|
||||
// 同一 (teaId, groupId) 可能跨多所学校,用 List 收集避免重复键被丢弃
|
||||
Map<String, List<SchTeacherGroup>> groupMap = schTeacherGroupRepository.findByTeaIdIn(allUserIds).stream()
|
||||
.collect(Collectors.groupingBy(g -> buildTeacherGroupKey(g.getTeaId(), g.getGroupId())));
|
||||
List<SchTeacherGroup> toDeleteGroups = new ArrayList<>();
|
||||
for (DeleteUser du : teacherDeletes) {
|
||||
String key = buildTeacherGroupKey(du.getUserId(), du.getGroupId());
|
||||
SchTeacherGroup group = groupMap.get(key);
|
||||
if (group != null) {
|
||||
toDeleteGroups.add(group);
|
||||
for (DeleteUser du : validDeletes) {
|
||||
List<SchTeacherGroup> groups = groupMap.get(buildTeacherGroupKey(du.getUserId(), du.getGroupId()));
|
||||
if (groups != null) {
|
||||
toDeleteGroups.addAll(groups);
|
||||
}
|
||||
}
|
||||
|
||||
if (!toDeleteGroups.isEmpty()) {
|
||||
// 按学校维度分组,用于缓存清除和剩余分组检查
|
||||
Map<Integer, List<SchTeacherGroup>> groupsBySchool = toDeleteGroups.stream()
|
||||
.collect(Collectors.groupingBy(SchTeacherGroup::getSchId));
|
||||
|
||||
// 先清除缓存(针对每个分组所属学校)
|
||||
for (SchTeacherGroup group : toDeleteGroups) {
|
||||
schTeacherCacheService.clearTeacherCache(group.getSchId());
|
||||
}
|
||||
|
||||
// 物理删除分组
|
||||
// 按学校维度去重后清除缓存
|
||||
Set<Integer> schIds = toDeleteGroups.stream()
|
||||
.map(SchTeacherGroup::getSchId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
schTeacherCacheService.clearTeacherCaches(schIds);
|
||||
schTeacherGroupRepository.deleteAll(toDeleteGroups);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 角色判断 ====================
|
||||
private boolean isStudent(BaseUser user) {
|
||||
if (user.getRoleList() == null) return false;
|
||||
|
||||
/**
|
||||
* 提取用户的角色 id 集合(去重、过滤空值),每个用户仅遍历一次。
|
||||
*/
|
||||
private Set<Integer> collectRoleIds(SyncUserDTO user) {
|
||||
if (user.getRoleList() == null) return Collections.emptySet();
|
||||
return user.getRoleList().stream()
|
||||
.anyMatch(r -> r.getRoleId() != null && r.getRoleId().equals(UserRole.STU_USER.getValue()));
|
||||
.filter(Objects::nonNull)
|
||||
.map(SyncUserRoleDTO::getRoleId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean isTeacher(BaseUser user) {
|
||||
if (user.getRoleList() == null) return false;
|
||||
return user.getRoleList().stream()
|
||||
.anyMatch(r -> r.getRoleId() != null &&
|
||||
(r.getRoleId().equals(UserRole.TEACHER_USER.getValue()) ||
|
||||
r.getRoleId().equals(UserRole.SCH_LEADER_USER.getValue())));
|
||||
private boolean isStudent(Set<Integer> roleIds) {
|
||||
return roleIds.contains(UserRole.STU_USER.getValue());
|
||||
}
|
||||
|
||||
private boolean isTeacher(Set<Integer> roleIds) {
|
||||
return roleIds.contains(UserRole.TEACHER_USER.getValue())
|
||||
|| roleIds.contains(UserRole.SCH_LEADER_USER.getValue());
|
||||
}
|
||||
|
||||
// ==================== 学生同步 ====================
|
||||
private void syncStudents(List<BaseUser> studentUsers, Date now) {
|
||||
List<Integer> stuIds = studentUsers.stream().map(BaseUser::getId).distinct().collect(Collectors.toList());
|
||||
|
||||
private void syncStudents(List<SyncUserDTO> studentUsers, Date now) {
|
||||
List<Integer> stuIds = studentUsers.stream().map(SyncUserDTO::getId).distinct().collect(Collectors.toList());
|
||||
|
||||
// 已有学生记录 (stuId, groupId) -> SchStudent
|
||||
Map<String, SchStudent> studentMap = schStudentRepository.findByStuIdIn(stuIds)
|
||||
.stream()
|
||||
Map<String, SchStudent> studentMap = schStudentRepository.findByStuIdIn(stuIds).stream()
|
||||
.collect(Collectors.toMap(
|
||||
s -> buildStudentKey(s.getStuId(), s.getGroupId()),
|
||||
Function.identity()
|
||||
));
|
||||
|
||||
List<SchStudent> saveList = new ArrayList<>();
|
||||
// 受影响班级缓存键 (schId -> classId 集合),用于同步后失效
|
||||
Map<Integer, Set<Integer>> classKeys = new HashMap<>();
|
||||
|
||||
for (BaseUser user : studentUsers) {
|
||||
for (SyncUserDTO user : studentUsers) {
|
||||
if (user.getGroups() == null) continue;
|
||||
for (BaseUser.GroupInfo group : user.getGroups()) {
|
||||
|
||||
for (SyncUserGroupDTO group : user.getGroups()) {
|
||||
Integer groupId = group.getGroupId();
|
||||
Integer schId = group.getSchoolId();
|
||||
if (groupId == null || schId == null) continue;
|
||||
@@ -201,21 +194,18 @@ public class SyncUserService implements ISyncUserService {
|
||||
student = createStudent(user, group, now);
|
||||
}
|
||||
saveList.add(student);
|
||||
classKeys.computeIfAbsent(schId, k -> new HashSet<>()).add(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!saveList.isEmpty()) {
|
||||
schStudentRepository.saveAll(saveList);
|
||||
// 缓存:将学生加入班级缓存(Set结构)
|
||||
// for (SchStudent stu : saveList) {
|
||||
// if (stu.getSchId() != null && stu.getGroupId() != null) {
|
||||
// schStudentCacheService.addClassStudentCache(stu.getSchId(), stu.getGroupId(), stu.getStuId());
|
||||
// }
|
||||
// }
|
||||
// 同步后使受影响班级的学生缓存失效,避免读到旧数据
|
||||
classKeys.forEach((schId, classIds) -> schStudentCacheService.clearClassStudentCaches(schId, classIds));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStudent(SchStudent student, BaseUser user, BaseUser.GroupInfo group, Date now) {
|
||||
private void updateStudent(SchStudent student, SyncUserDTO user, SyncUserGroupDTO group, Date now) {
|
||||
student.setAccount(user.getAccount());
|
||||
student.setName(user.getName());
|
||||
student.setGender(user.getGender());
|
||||
@@ -228,7 +218,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
student.setUpdateDate(now);
|
||||
}
|
||||
|
||||
private SchStudent createStudent(BaseUser user, BaseUser.GroupInfo group, Date now) {
|
||||
private SchStudent createStudent(SyncUserDTO user, SyncUserGroupDTO group, Date now) {
|
||||
SchStudent student = new SchStudent();
|
||||
student.setStuId(user.getId());
|
||||
student.setAccount(user.getAccount());
|
||||
@@ -248,17 +238,16 @@ public class SyncUserService implements ISyncUserService {
|
||||
}
|
||||
|
||||
// ==================== 教师同步 ====================
|
||||
private void syncTeachers(List<BaseUser> teacherUsers, Date now) {
|
||||
List<Integer> teaIds = teacherUsers.stream().map(BaseUser::getId).distinct().collect(Collectors.toList());
|
||||
|
||||
private void syncTeachers(List<SyncUserDTO> teacherUsers, Date now) {
|
||||
List<Integer> teaIds = teacherUsers.stream().map(SyncUserDTO::getId).distinct().collect(Collectors.toList());
|
||||
|
||||
// 教师主体(唯一)
|
||||
Map<Integer, SchTeacher> teacherMap = schTeacherRepository.findByTeaIdIn(teaIds)
|
||||
.stream()
|
||||
Map<Integer, SchTeacher> teacherMap = schTeacherRepository.findByTeaIdIn(teaIds).stream()
|
||||
.collect(Collectors.toMap(SchTeacher::getTeaId, Function.identity()));
|
||||
|
||||
// 教师分组 (teaId, groupId, schId) -> SchTeacherGroup
|
||||
Map<String, SchTeacherGroup> groupMap = schTeacherGroupRepository.findByTeaIdIn(teaIds)
|
||||
.stream()
|
||||
Map<String, SchTeacherGroup> groupMap = schTeacherGroupRepository.findByTeaIdIn(teaIds).stream()
|
||||
.collect(Collectors.toMap(
|
||||
g -> buildTeacherGroupKeyWithSchId(g.getTeaId(), g.getGroupId(), g.getSchId()),
|
||||
Function.identity()
|
||||
@@ -266,8 +255,10 @@ public class SyncUserService implements ISyncUserService {
|
||||
|
||||
List<SchTeacher> saveTeacherList = new ArrayList<>();
|
||||
List<SchTeacherGroup> saveGroupList = new ArrayList<>();
|
||||
// 受影响学校缓存键,用于同步后失效
|
||||
Set<Integer> schIds = new HashSet<>();
|
||||
|
||||
for (BaseUser user : teacherUsers) {
|
||||
for (SyncUserDTO user : teacherUsers) {
|
||||
// 教师主体(只存一条)
|
||||
SchTeacher teacher = teacherMap.get(user.getId());
|
||||
if (teacher != null) {
|
||||
@@ -279,7 +270,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
|
||||
// 教师分组(遍历 groups)
|
||||
if (user.getGroups() == null) continue;
|
||||
for (BaseUser.GroupInfo group : user.getGroups()) {
|
||||
for (SyncUserGroupDTO group : user.getGroups()) {
|
||||
Integer groupId = group.getGroupId();
|
||||
Integer schId = group.getSchoolId();
|
||||
if (groupId == null || schId == null) continue;
|
||||
@@ -293,6 +284,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
tg = createTeacherGroup(user, group, now);
|
||||
}
|
||||
saveGroupList.add(tg);
|
||||
schIds.add(schId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,18 +293,14 @@ public class SyncUserService implements ISyncUserService {
|
||||
}
|
||||
if (!saveGroupList.isEmpty()) {
|
||||
schTeacherGroupRepository.saveAll(saveGroupList);
|
||||
// // 缓存:更新教师缓存(学校维度)
|
||||
// // 为简单起见,清除每个涉及的学校缓存,然后重新添加该学校所有教师(但这里我们只添加本次更新的教师,因为Set可重复)
|
||||
// // 更稳健:清除后重建,但为了减少数据库查询,我们使用 add 方法
|
||||
// for (SchTeacherGroup g : saveGroupList) {
|
||||
// if (g.getSchId() != null) {
|
||||
// schTeacherCacheService.addSchoolTeacherCache(g.getSchId(), g.getTeaId());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// 同步后使受影响学校的教师缓存失效
|
||||
if (!schIds.isEmpty()) {
|
||||
schTeacherCacheService.clearTeacherCaches(schIds);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTeacher(SchTeacher teacher, BaseUser user, Date now) {
|
||||
private void updateTeacher(SchTeacher teacher, SyncUserDTO user, Date now) {
|
||||
teacher.setAccount(user.getAccount());
|
||||
teacher.setName(user.getName());
|
||||
teacher.setGender(user.getGender());
|
||||
@@ -322,7 +310,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
teacher.setUpdateDate(now);
|
||||
}
|
||||
|
||||
private SchTeacher createTeacher(BaseUser user, Date now) {
|
||||
private SchTeacher createTeacher(SyncUserDTO user, Date now) {
|
||||
SchTeacher teacher = new SchTeacher();
|
||||
teacher.setTeaId(user.getId());
|
||||
teacher.setAccount(user.getAccount());
|
||||
@@ -336,7 +324,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
return teacher;
|
||||
}
|
||||
|
||||
private SchTeacherGroup createTeacherGroup(BaseUser user, BaseUser.GroupInfo group, Date now) {
|
||||
private SchTeacherGroup createTeacherGroup(SyncUserDTO user, SyncUserGroupDTO group, Date now) {
|
||||
SchTeacherGroup tg = new SchTeacherGroup();
|
||||
tg.setTeaId(user.getId());
|
||||
tg.setGroupId(group.getGroupId());
|
||||
@@ -346,6 +334,7 @@ public class SyncUserService implements ISyncUserService {
|
||||
}
|
||||
|
||||
// ==================== 辅助键生成 ====================
|
||||
|
||||
private String buildStudentKey(Integer stuId, Integer groupId) {
|
||||
return stuId + "_" + groupId;
|
||||
}
|
||||
|
||||
@@ -263,12 +263,16 @@ public class OtherUtil {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 使用 TypeReference 保留泛型信息,避免类型擦除
|
||||
return objectMapper.readValue(json, new TypeReference<List<T>>() {});
|
||||
// 注意:new TypeReference<List<T>>() {} 会因泛型擦除退化为原始 List,
|
||||
// 元素被反序列化为 LinkedHashMap,后续强转目标类型会抛 ClassCastException。
|
||||
// 必须用 TypeFactory 动态构建 List<T> 的 JavaType 才能保留元素类型。
|
||||
JavaType listType = objectMapper.getTypeFactory()
|
||||
.constructCollectionType(List.class, targetClass);
|
||||
return objectMapper.readValue(json, listType);
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析 JSON 数组失败,json 前缀: " + json);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new DException("解析 JSON 数组失败!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,9 +290,9 @@ public class OtherUtil {
|
||||
try {
|
||||
return objectMapper.readValue(json, targetClass);
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析 JSON 数组失败,json 前缀: " + json);
|
||||
System.err.println("解析 JSON 对象失败,json 前缀: " + json);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new DException("解析 JSON 对象失败!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +309,7 @@ public class OtherUtil {
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析 JSON 数组失败: " + json);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new DException("解析 JSON 数组失败!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +324,7 @@ public class OtherUtil {
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析 JSON 数组失败: " + json);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new DException("解析 JSON 数组失败!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user