From 9186fe6d34c3663ee1873949c460ef1e4b089423 Mon Sep 17 00:00:00 2001 From: wantaek Date: Thu, 17 Sep 2026 18:51:35 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EA=B6=8C=ED=95=9C=20=EA=B7=B8=EB=A3=B9?= =?UTF-8?q?=20=EB=B0=B0=EC=A0=95=20=EB=AA=A9=EB=A1=9D=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EB=8B=A8=EC=9D=BC=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=EC=9C=BC=EB=A1=9C=20=EB=AC=B6=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rgm/service/EgovAuthorGroupService.java | 4 ++ .../impl/EgovAuthorGroupServiceImpl.java | 25 ++++++++ .../rgm/web/EgovAuthorGroupAPIController.java | 17 +---- .../EgovAuthorGroupServiceImplBatchTest.java | 64 +++++++++++++++++++ 4 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 EgovAuthor/src/test/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImplBatchTest.java diff --git a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/EgovAuthorGroupService.java b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/EgovAuthorGroupService.java index b62e28a9..03fc40c5 100644 --- a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/EgovAuthorGroupService.java +++ b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/EgovAuthorGroupService.java @@ -17,4 +17,8 @@ public interface EgovAuthorGroupService { void delete(AuthorGroupVO authorGroupVO, Map userInfo); + void insertOrUpdateList(String[] userIds, String[] mberTyCodes, String[] authorCodes, String[] regYns, AuthorGroupVO authorGroupVO); + + void deleteList(String[] userIds, AuthorGroupVO authorGroupVO, Map userInfo); + } diff --git a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImpl.java b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImpl.java index aa28b3f3..dc55801d 100644 --- a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImpl.java +++ b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImpl.java @@ -168,6 +168,31 @@ public void delete(AuthorGroupVO authorGroupVO, Map userInfo) { repository.deleteById(scrtyDtrmnTrgetId); } + @Transactional + @Override + public void insertOrUpdateList(String[] userIds, String[] mberTyCodes, String[] authorCodes, String[] regYns, AuthorGroupVO authorGroupVO) { + for (int i = 0; i < userIds.length; i++) { + authorGroupVO.setScrtyDtrmnTrgetId(userIds[i]); + authorGroupVO.setMberTyCode(mberTyCodes[i]); + authorGroupVO.setAuthorCode(authorCodes[i]); + + if ("N".equals(regYns[i])) { + this.insert(authorGroupVO); + } else { + this.update(authorGroupVO); + } + } + } + + @Transactional + @Override + public void deleteList(String[] userIds, AuthorGroupVO authorGroupVO, Map userInfo) { + for (String userId : userIds) { + authorGroupVO.setScrtyDtrmnTrgetId(userId); + this.delete(authorGroupVO, userInfo); + } + } + private void requireAuthenticated(Map userInfo) { if (userInfo == null || ObjectUtils.isEmpty(userInfo.get("uniqId"))) { throw new IllegalStateException("인증 정보가 없습니다."); diff --git a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/web/EgovAuthorGroupAPIController.java b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/web/EgovAuthorGroupAPIController.java index 057f8804..eaab3eec 100644 --- a/EgovAuthor/src/main/java/egovframework/com/sec/rgm/web/EgovAuthorGroupAPIController.java +++ b/EgovAuthor/src/main/java/egovframework/com/sec/rgm/web/EgovAuthorGroupAPIController.java @@ -76,17 +76,7 @@ public ResponseEntity authorGroupInsert( String[] strAuthorCodes = authorCode.split(";"); String[] strRegYns = regYns.split(";"); - for (int i = 0; i < strUserIds.length; i++) { - authorGroupVO.setScrtyDtrmnTrgetId(strUserIds[i]); - authorGroupVO.setMberTyCode(strMberTyCodes[i]); - authorGroupVO.setAuthorCode(strAuthorCodes[i]); - - if ("N".equals(strRegYns[i])) { - service.insert(authorGroupVO); - } else { - service.update(authorGroupVO); - } - } + service.insertOrUpdateList(strUserIds, strMberTyCodes, strAuthorCodes, strRegYns, authorGroupVO); return ResponseEntity.ok().build(); } @@ -95,10 +85,7 @@ public ResponseEntity authorGroupInsert( public ResponseEntity authorGroupDelete(@RequestParam String userIds, @ModelAttribute AuthorGroupVO authorGroupVO, HttpServletRequest request) { Map userInfo = extracted(request); String[] strUserIds = userIds.split(";"); - for (String strUserId : strUserIds) { - authorGroupVO.setScrtyDtrmnTrgetId(strUserId); - service.delete(authorGroupVO, userInfo); - } + service.deleteList(strUserIds, authorGroupVO, userInfo); return ResponseEntity.ok().build(); } diff --git a/EgovAuthor/src/test/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImplBatchTest.java b/EgovAuthor/src/test/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImplBatchTest.java new file mode 100644 index 00000000..48af57b8 --- /dev/null +++ b/EgovAuthor/src/test/java/egovframework/com/sec/rgm/service/impl/EgovAuthorGroupServiceImplBatchTest.java @@ -0,0 +1,64 @@ +package egovframework.com.sec.rgm.service.impl; + +import egovframework.com.sec.rgm.entity.Emplyrscrtyestbs; +import egovframework.com.sec.rgm.repository.EgovAuthorGroupRepository; +import egovframework.com.sec.rgm.service.AuthorGroupVO; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * authorGroupInsert·authorGroupDelete가 항목마다 서비스를 따로 호출하던 것을 + * 서비스 메서드 하나로 옮겼다. 컨트롤러 루프가 매 항목마다 별도 트랜잭션을 여는 + * insert·update·delete를 직접 호출해, 루프 중간에 예외가 나면 그 뒤 항목은 + * 반영되지 않고 앞 항목만 커밋된 채 남을 수 있었다. + */ +class EgovAuthorGroupServiceImplBatchTest { + + private final EgovAuthorGroupRepository repository = mock(EgovAuthorGroupRepository.class); + private final EgovAuthorGroupServiceImpl service = new EgovAuthorGroupServiceImpl(repository, null, null); + + @Test + void insertOrUpdateListInsertsNewAndUpdatesExisting() { + when(repository.save(any())).thenAnswer(invocation -> invocation.getArgument(0)); + Emplyrscrtyestbs existing = new Emplyrscrtyestbs(); + existing.setScrtyDtrmnTrgetId("U02"); + existing.setMberTyCode("USR"); + existing.setAuthorCode("OLDCODE"); + when(repository.findById("U02")).thenReturn(Optional.of(existing)); + + String[] userIds = {"U01", "U02"}; + String[] mberTyCodes = {"USR", "USR"}; + String[] authorCodes = {"A01", "A02"}; + String[] regYns = {"N", "Y"}; + + service.insertOrUpdateList(userIds, mberTyCodes, authorCodes, regYns, new AuthorGroupVO()); + + ArgumentCaptor saved = ArgumentCaptor.forClass(Emplyrscrtyestbs.class); + verify(repository, times(2)).save(saved.capture()); + assertThat(saved.getAllValues()) + .extracting(Emplyrscrtyestbs::getScrtyDtrmnTrgetId) + .containsExactly("U01", "U02"); + assertThat(saved.getAllValues().get(1).getAuthorCode()).isEqualTo("A02"); + } + + @Test + void deleteListDeletesEachUserWithAuthenticatedCaller() { + String[] userIds = {"U01", "U02", "U03"}; + Map userInfo = new HashMap<>(); + userInfo.put("uniqId", "admin1"); + + service.deleteList(userIds, new AuthorGroupVO(), userInfo); + + verify(repository, times(1)).deleteById("U01"); + verify(repository, times(1)).deleteById("U02"); + verify(repository, times(1)).deleteById("U03"); + } +}