yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/api/employee/HrmEmployeeApiImpl.java
@@ -10,6 +10,7 @@ import org.springframework.stereotype.Service; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -51,7 +52,9 @@ // æ¹éæ¥é¨é¨ï¼é¿å N+1 List<Long> deptIds = employees.stream().map(HrmEmployeeDO::getDeptId) .filter(Objects::nonNull).distinct().toList(); Map<Long, DeptRespDTO> deptMap = deptIds.isEmpty() ? Map.of() : deptApi.getDeptMap(deptIds); // ç¨ new HashMap<>() èé Map.of()ï¼åå·¥ç deptId å è®¸ä¸ºç©ºï¼ // åé¢ deptMap.get(e.getDeptId()) ä¼ get(null)ï¼Map.of() ç get(null) æ NPEã Map<Long, DeptRespDTO> deptMap = deptIds.isEmpty() ? new HashMap<>() : deptApi.getDeptMap(deptIds); return employees.stream() .map(e -> { DeptRespDTO dept = deptMap.get(e.getDeptId()); yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyCertificateService.java
@@ -19,6 +19,7 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -101,7 +102,10 @@ List<Long> employeeIds = certs.stream() .map(SafetyCertificateDO::getEmployeeId) .filter(Objects::nonNull).distinct().toList(); Map<Long, HrmEmployeeSimpleDTO> employeeMap = employeeIds.isEmpty() ? Map.of() // ç¨ new HashMap<>() èé Map.of()ï¼employeeId å 许为 nullï¼ // åé¢ employeeMap.get(cert.getEmployeeId()) å¨ç©ºéååºæ¯ä¼ get(null)ï¼ // Map.of() ç get(null) 伿 NPE 导è´è¯ä»¶å表æ¥å£ 500ã Map<Long, HrmEmployeeSimpleDTO> employeeMap = employeeIds.isEmpty() ? new HashMap<>() : hrmEmployeeApi.getEmployeeList(employeeIds).stream() .collect(Collectors.toMap(HrmEmployeeSimpleDTO::getId, e -> e, (a, b) -> a)); certs.forEach(cert -> { yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRefResolver.java
@@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -65,12 +66,15 @@ * æ¹éååå·¥ï¼è¿å id -> åå·¥ ç Map */ public Map<Long, HrmEmployeeSimpleDTO> employeeMap(Collection<Long> employeeIds) { // 注æï¼è¿éå¿ é¡»è¿å坿¥å null key ç空 Mapã // è°ç¨æ¹ä¼ç´æ¥ map.get(è®°å½éç xxxId)ï¼è xxxId å 许为 nullï¼ä¾å¦ç»ç»æªè®¾è´è´£äººã // è¯ä»¶æªå ³èæè¯äººï¼ï¼Map.of() ç get(null) 伿 NPEï¼å¯¼è´å表æ¥å£ 500ã if (CollUtil.isEmpty(employeeIds)) { return Map.of(); return new HashMap<>(); } List<Long> ids = employeeIds.stream().filter(Objects::nonNull).distinct().toList(); if (ids.isEmpty()) { return Map.of(); return new HashMap<>(); } return hrmEmployeeApi.getEmployeeList(ids).stream() .collect(Collectors.toMap(HrmEmployeeSimpleDTO::getId, e -> e, (a, b) -> a)); @@ -103,12 +107,13 @@ * æ¹éå车é´ï¼è¿å id -> è½¦é´ ç Map */ public Map<Long, MesMdWorkshopDO> workshopMap(Collection<Long> workshopIds) { // åä¸ï¼è½¦é´ç¼å·å 许为 nullï¼ç©ºéåå¿ é¡»è¿å坿¥å null key ç Map if (CollUtil.isEmpty(workshopIds)) { return Map.of(); return new HashMap<>(); } List<Long> ids = workshopIds.stream().filter(Objects::nonNull).distinct().toList(); if (ids.isEmpty()) { return Map.of(); return new HashMap<>(); } return workshopMapper.selectBatchIds(ids).stream() .collect(Collectors.toMap(MesMdWorkshopDO::getId, w -> w, (a, b) -> a)); yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/safety/SafetyRefResolverEmptyCollectionTest.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,105 @@ package cn.iocoder.yudao.module.mes.service.safety; import cn.iocoder.yudao.module.hrm.api.employee.HrmEmployeeApi; import cn.iocoder.yudao.module.hrm.api.employee.dto.HrmEmployeeSimpleDTO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** * {@link SafetyRefResolver} 空éååºæ¯å彿µè¯ * * <p>èæ¯ï¼{@code Map.of()} æ¯ç©ºä¸ä¸å¯åç Mapï¼å®ç {@code get(null)} 伿 NPEï¼ * è {@code Map.of().get(énull)} ä¸ä¼ãå®å ¨ç产模åéãç»ç» / è¯ä»¶ / 鿣ãç * è®°å½å¨æªå ³èåå·¥ï¼leaderIdãemployeeId 为 nullï¼æ¶ï¼å°±ä¼èµ°å° {@code map.get(null)}ï¼ * ä»èå¨åè¡¨é¡µç´æ¥ 500ã</p> * * <p>è¿ééæ»çº¦å®ï¼ç©ºéåå¿ é¡»è¿å坿¥å null key ç空 Mapã</p> */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) class SafetyRefResolverEmptyCollectionTest { @InjectMocks private SafetyRefResolver resolver; @Mock private HrmEmployeeApi hrmEmployeeApi; @Mock private cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkshopMapper workshopMapper; /** 空éåï¼å¿ é¡»è½ get(null) è䏿 NPEï¼è¿å°±æ¯çº¿ä¸ NPE çæ ¹å ï¼ */ @Test void employeeMap_emptyCollection_getNullShouldNotThrow() { Map<Long, HrmEmployeeSimpleDTO> map = resolver.employeeMap(List.of()); assertTrue(map.isEmpty()); // Map.of() å¨è¿é伿 NullPointerException assertNull(map.get(null), "空éåè¿åç Map å¿ é¡»å è®¸ç¨ null ä½ä¸º key æ¥è¯¢"); } /** éåéå ¨æ¯ nullï¼è¿æ»¤å为空ï¼åæ ·å¿ é¡»è½ get(null) */ @Test void employeeMap_allNullElements_getNullShouldNotThrow() { Map<Long, HrmEmployeeSimpleDTO> map = resolver.employeeMap(java.util.Arrays.asList((Long) null, null)); assertTrue(map.isEmpty()); assertNull(map.get(null)); } /** null éåæ¬èº« */ @Test void employeeMap_nullCollection_getNullShouldNotThrow() { Map<Long, HrmEmployeeSimpleDTO> map = resolver.employeeMap(null); assertTrue(map.isEmpty()); assertNull(map.get(null)); } @Test void workshopMap_emptyCollection_getNullShouldNotThrow() { Map<Long, MesMdWorkshopDO> map = resolver.workshopMap(List.of()); assertTrue(map.isEmpty()); assertNull(map.get(null), "空éåè¿åç Map å¿ é¡»å è®¸ç¨ null ä½ä¸º key æ¥è¯¢"); } @Test void workshopMap_allNullElements_getNullShouldNotThrow() { Map<Long, MesMdWorkshopDO> map = resolver.workshopMap(java.util.Arrays.asList((Long) null)); assertTrue(map.isEmpty()); assertNull(map.get(null)); } @Test void workshopMap_nullCollection_getNullShouldNotThrow() { Map<Long, MesMdWorkshopDO> map = resolver.workshopMap(null); assertTrue(map.isEmpty()); assertNull(map.get(null)); } /** è¿åç Map åºè¯¥æ¯å¯åçï¼é¿å åç» put æ UnsupportedOperationExceptionï¼ */ @Test void employeeMap_emptyResultShouldBeMutable() { Map<Long, HrmEmployeeSimpleDTO> map = resolver.employeeMap(List.of()); map.put(1L, new HrmEmployeeSimpleDTO()); assertEquals(1, map.size()); } @Test void workshopMap_emptyResultShouldBeMutable() { Map<Long, MesMdWorkshopDO> map = resolver.workshopMap(List.of()); map.put(1L, new MesMdWorkshopDO()); assertEquals(1, map.size()); } } yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java
@@ -28,6 +28,7 @@ import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -86,7 +87,9 @@ Set<Long> userIds = responses.stream() .filter(log -> Objects.equals(log.getUserType(), UserTypeEnum.ADMIN.getValue())) .map(OperateLogRespVO::getUserId).filter(Objects::nonNull).collect(Collectors.toSet()); Map<Long, AdminUserDO> users = userIds.isEmpty() ? Map.of() : adminUserService.getUserMap(userIds); // ç¨ new HashMap<>() èé Map.of()ï¼ä¸é¢ä¼æ log.getUserId() åå¼ï¼ // é管çå忝è½ç¶å·²å¤ç©ºï¼ä½ä¿æä¸è´çåæ³å¯é¿å 以忹å¨è¸©å° Map.of() ç get(null) NPEã Map<Long, AdminUserDO> users = userIds.isEmpty() ? new HashMap<>() : adminUserService.getUserMap(userIds); for (OperateLogRespVO log : responses) { if (log.getUserId() == null) { log.setUserName("æªç¥æä½äºº");