From 8ff5ac68f095f8c7b1ebc15bb2702ed7c0a96e01 Mon Sep 17 00:00:00 2001 From: Moon Date: Fri, 26 Dec 2025 15:13:27 +0900 Subject: [PATCH] =?UTF-8?q?=EC=98=81=EC=83=81=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapsheet/MapSheetMngApiController.java | 42 ++--- .../mapsheet/dto/MapSheetMngDto.java | 26 +-- .../mapsheet/service/MapSheetMngService.java | 53 +++--- .../postgres/core/MapSheetMngCoreService.java | 157 +----------------- .../mapsheet/MapSheetMngRepositoryCustom.java | 4 +- .../mapsheet/MapSheetMngRepositoryImpl.java | 24 +-- 6 files changed, 72 insertions(+), 234 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java index e3f343de..103d93e2 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java @@ -178,20 +178,22 @@ public class MapSheetMngApiController { return ApiResponseDto.ok(mapSheetMngService.updateExceptUseInference(hstUidList)); } + + + */ + @Operation(summary = "페어 파일 업로드", description = "TFW/TIF 두 파일을 쌍으로 업로드 및 검증") @PostMapping(value = "/upload-pair", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ApiResponseDto uploadPair( - @RequestPart("tfw") MultipartFile tfwFile, - @RequestPart("tif") MultipartFile tifFile, - @RequestParam(value = "hstUid", required = false) Long hstUid, - @RequestParam(value = "overwrite", required = false) boolean overwrite) { + @RequestPart("tfw") MultipartFile tfwFile, + @RequestPart("tif") MultipartFile tifFile, + @RequestParam(value = "hstUid", required = false) Long hstUid, + @RequestParam(value = "overwrite", required = false) boolean overwrite) { return ApiResponseDto.createOK( - mapSheetMngService.uploadPair(tfwFile, tifFile, hstUid, overwrite)); + mapSheetMngService.uploadPair(tfwFile, tifFile, hstUid, overwrite)); } - */ - @Operation(summary = "영상관리 > 파일조회", description = "영상관리 > 파일조회") @ApiResponses( value = { @@ -207,33 +209,13 @@ public class MapSheetMngApiController { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @GetMapping("/mng-file-list") - public ApiResponseDto> findHstUidToMapSheetFileList( + public ApiResponseDto> findByHstUidMapSheetFileList( @RequestParam @Valid Long hstUid) { - return ApiResponseDto.ok(mapSheetMngService.findHstUidToMapSheetFileList(hstUid)); - } - - @Operation(summary = "영상관리 > 파일삭제", description = "영상관리 > 파일삭제") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "파일삭제 처리 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Long.class))), - @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) - @PutMapping("/del-mng-files") - public ApiResponseDto deleteByFileUidMngFile( - @RequestParam @Valid List fileUids) { - return ApiResponseDto.ok(mapSheetMngService.deleteByFileUidMngFile(fileUids)); + return ApiResponseDto.ok(mapSheetMngService.findByHstUidMapSheetFileList(hstUid)); } - @Operation(summary = "영상관리 > 파일사용설정", description = "영상관리 > 파일사용설정(중복파일제거 및 선택파일사용설정)") + @Operation(summary = "영상관리 > 파일사용설정 및 중복제거", description = "영상관리 >파일사용설정 및 중복제거(중복파일제거 및 선택파일사용설정)") @ApiResponses( value = { @ApiResponse( diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java index f76f9143..9e5b0b38 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java @@ -90,16 +90,7 @@ public class MapSheetMngDto { @JsonFormatDttm private ZonedDateTime rgstStrtDttm; @JsonFormatDttm private ZonedDateTime rgstEndDttm; - public String getMngState() { - if (this.syncStateDoneCnt == 0) return "NOTYET"; - else if (this.syncStateDoneCnt < this.syncTotCnt) return "PROCESSING"; - - if ((this.syncNotPaireExecCnt + this.syncDuplicateExecCnt + this.syncFaultExecCnt) > 0) - return "TAKINGERROR"; - - return "DONE"; - } public String getSyncState() { @@ -139,8 +130,22 @@ public class MapSheetMngDto { return this.syncNotPaireExecCnt + this.syncDuplicateExecCnt + this.syncFaultExecCnt; } + + public String getMngState() { + + String mngState = "DONE"; + + if (this.syncStateDoneCnt == 0) mngState = "NOTYET"; + else if (this.syncStateDoneCnt < this.syncTotCnt) mngState = "PROCESSING"; + + if ((this.syncNotPaireExecCnt + this.syncDuplicateExecCnt + this.syncFaultExecCnt) > 0) + mngState = "TAKINGERROR"; + + return mngState; + } + public String getMngStateName() { - String enumId = this.mngState; + String enumId = this.getMngState(); if (enumId == null || enumId.isEmpty()) { enumId = "NOTYET"; } @@ -148,6 +153,7 @@ public class MapSheetMngDto { MngStateType type = Enums.fromId(MngStateType.class, enumId); return type.getText(); } + } @Schema(name = "ErrorSearchReq", description = "영상관리 오류데이터 검색 요청") diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java index 127c4265..1e57c4b4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java @@ -73,13 +73,11 @@ public class MapSheetMngService { } @Transactional - public DmlReturn mngDataSave(AddReq AddReq) { - return mapSheetMngCoreService.mngDataSave(AddReq); + public DmlReturn mngDataSave(AddReq addReq) { + int execCnt = mapSheetMngCoreService.mngDataSave(addReq); + return new MapSheetMngDto.DmlReturn("success", addReq.getMngYyyy()+"년, "+execCnt+"건 생성"); } - public DmlReturn uploadProcess(@Valid List hstUidList) { - return mapSheetMngCoreService.uploadProcess(hstUidList); - } public DmlReturn updateExceptUseInference(@Valid List hstUidList) { return mapSheetMngCoreService.updateExceptUseInference(hstUidList); @@ -129,7 +127,7 @@ public class MapSheetMngService { if (!FIleChecker.checkTfw(tfwTmpPath)) return new DmlReturn("fail", "TFW TYPE ERROR"); // 싱크파일목록으로 업로드 경로 확인 - List mngFiles = mapSheetMngCoreService.findIdToMapSheetFileList(hstUid); + List mngFiles = mapSheetMngCoreService.findByHstUidMapSheetFileList(hstUid); String uploadPath = ""; for (MngFilesDto dto : mngFiles) { uploadPath = dto.getFilePath(); @@ -197,24 +195,10 @@ public class MapSheetMngService { return new DmlReturn("success", "파일 업로드 완료되었습니다."); } - public List findHstUidToMapSheetFileList(Long hstUid) { - return mapSheetMngCoreService.findHstUidToMapSheetFileList(hstUid); + public List findByHstUidMapSheetFileList(Long hstUid) { + return mapSheetMngCoreService.findByHstUidMapSheetFileList(hstUid); } - @Transactional - public DmlReturn deleteByFileUidMngFile(List fileUids) { - - long hstUid = 0; - - for (Long uid : fileUids) { - mapSheetMngCoreService.deleteByFileUidMngFile(uid); - } - - // 중복제거 확인후 처리상태(DONE)변경 - //if (hstUid > 0) mapSheetMngCoreService.updateByHstUidSyncCheckState(hstUid); - - return new DmlReturn("success", fileUids.size() + "개 파일이 삭제되었습니다."); - } @Transactional public DmlReturn setUseByFileUidMngFile(List fileUids) { @@ -223,21 +207,29 @@ public class MapSheetMngService { DmlReturn dmlReturn = new DmlReturn("success", "정상처리되었습니다."); - MapSheetMngDto.MngFilesDto dto = mapSheetMngCoreService.findByFileUidMapSheetFile(fileUids.get(0)); - hstUid = dto.getHstUid(); - - mapSheetMngCoreService.deleteByNotInFileUidMngFile(hstUid, fileUids); + MapSheetMngDto.SyncCheckStateReqUpdateDto reqDto = new MapSheetMngDto.SyncCheckStateReqUpdateDto(); for (Long uid : fileUids) { + MapSheetMngDto.MngFilesDto dto = mapSheetMngCoreService.findByFileUidMapSheetFile(uid); + + reqDto.setHstUid(dto.getHstUid()); + reqDto.setFilePath(dto.getFilePath()); + reqDto.setSyncCheckState("DONE"); + + if (dto.getFileExt().equals("tif")) reqDto.setSyncCheckTifFileName(dto.getFileName()); + else if (dto.getFileExt().equals("tfw")) reqDto.setSyncCheckTfwFileName(dto.getFileName()); + mapSheetMngCoreService.updateByFileUidFileState(uid, "DONE"); } + //선택제외 삭제처리 + mapSheetMngCoreService.deleteByNotInFileUidMngFile(reqDto.getHstUid(), fileUids); + //Hst(내역) 테이블 상태 업데이트 + mapSheetMngCoreService.updateByHstUidSyncCheckState(reqDto); + return new DmlReturn("success", fileUids.size() + "개 파일이 사용설정되었습니다."); } - - - public DmlReturn validationFile(MultipartFile tfwFile, MultipartFile tifFile) { if( !FIleChecker.validationMultipart(tfwFile) )return new DmlReturn("fail", "TFW SIZE 오류"); @@ -253,9 +245,6 @@ public class MapSheetMngService { int tfwCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tfwFileName); int tifCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tifFileName); - System.out.println("tfwCnt ==" + tfwCnt); - System.out.println("tifCnt ==" + tifCnt); - if (tfwCnt > 0 || tifCnt > 0) { String resMsg = ""; if (tfwCnt > 0) diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java index a7b31451..706be684 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java @@ -27,8 +27,6 @@ public class MapSheetMngCoreService { private final MapSheetMngRepository mapSheetMngRepository; - private static final String ORIGINAL_IMAGES_PATH = "/app/original-images"; - @Value("{spring.profiles.active}") private String activeEnv; @@ -53,7 +51,6 @@ public class MapSheetMngCoreService { } - public int findByYearFileNameFileCount(int mngYyyy, String fileName) { return mapSheetMngRepository.findByYearFileNameFileCount(mngYyyy, fileName); } @@ -61,7 +58,6 @@ public class MapSheetMngCoreService { public MapSheetMngDto.DmlReturn mngFileSave(@Valid MapSheetMngDto.MngFileAddReq addReq) { mapSheetMngRepository.mngFileSave(addReq); - // int hstCnt = mapSheetMngRepository.insertMapSheetOrgDataToMapSheetMngHst(saved.getMngYyyy()); return new MapSheetMngDto.DmlReturn("success", "파일정보저장되었습니다."); } @@ -79,8 +75,8 @@ public class MapSheetMngCoreService { return mapSheetMngRepository.findMapSheetError(hstUid); } - public List findIdToMapSheetFileList(Long hstUid) { - return mapSheetMngRepository.findIdToMapSheetFileList(hstUid); + public List findByHstUidMapSheetFileList(Long hstUid) { + return mapSheetMngRepository.findByHstUidMapSheetFileList(hstUid); } public MapSheetMngDto.MngFilesDto findYyyyToMapSheetFilePathRefer(int mngYyyy) { @@ -91,91 +87,7 @@ public class MapSheetMngCoreService { return mapSheetMngRepository.findByFileUidMapSheetFile(fileUid); } - public MapSheetMngDto.DmlReturn uploadProcess(@Valid List hstUidList) { - int count = 0; - if (!Objects.isNull(hstUidList) && !hstUidList.isEmpty()) { - for (Long hstUid : hstUidList) { - Optional entity = - Optional.ofNullable( - mapSheetMngRepository - .findMapSheetMngHstInfo(hstUid) - .orElseThrow(EntityNotFoundException::new)); - String localPath = ""; - String rootDir = ORIGINAL_IMAGES_PATH + "/" + entity.get().getMngYyyy(); - if (activeEnv.equals("local")) { - rootDir = localPath + rootDir; - } - - String filename = entity.get().getMapSheetNum(); - String[] extensions = {"tif", "tfw"}; - boolean flag = allExtensionsExist(rootDir, filename, extensions); - if (flag) { - count += 1; - } - - // 파일 크기 계산 및 저장 - try (Stream paths = Files.walk(Paths.get(rootDir))) { - List matched = - paths - .filter(Files::isRegularFile) - .filter( - p -> { - String name = p.getFileName().toString(); - return name.equals(filename + ".tif") || name.equals(filename + ".tfw"); - }) - .collect(Collectors.toList()); - - long tifSize = - matched.stream() - .filter(p -> p.getFileName().toString().endsWith(".tif")) - .mapToLong( - p -> { - try { - return Files.size(p); - } catch (IOException e) { - return 0L; - } - }) - .sum(); - - long tfwSize = - matched.stream() - .filter(p -> p.getFileName().toString().endsWith(".tfw")) - .mapToLong( - p -> { - try { - return Files.size(p); - } catch (IOException e) { - return 0L; - } - }) - .sum(); - - entity.get().setTifSizeBytes(tifSize); - entity.get().setTfwSizeBytes(tfwSize); - entity.get().setTotalSizeBytes(tifSize + tfwSize); - - // 엔터티 저장 -> 커스텀 업데이트로 변경 - mapSheetMngRepository.updateHstFileSizes( - entity.get().getHstUid(), tifSize, tfwSize, tifSize + tfwSize); - } catch (IOException e) { - // 크기 계산 실패 시 0으로 저장 - entity.get().setTifSizeBytes(0L); - entity.get().setTfwSizeBytes(0L); - entity.get().setTotalSizeBytes(0L); - mapSheetMngRepository.updateHstFileSizes(entity.get().getHstUid(), 0L, 0L, 0L); - } - - /* - MapSheetMngDto.DataState dataState = - flag ? MapSheetMngDto.DataState.SUCCESS : MapSheetMngDto.DataState.FAIL; - entity.get().updateDataState(dataState); - */ - } - } - return new MapSheetMngDto.DmlReturn("success", count + "개 업로드 성공하였습니다."); - } public MapSheetMngDto.DmlReturn updateExceptUseInference(@Valid List hstUidList) { if (!Objects.isNull(hstUidList) && !hstUidList.isEmpty()) { @@ -192,40 +104,9 @@ public class MapSheetMngCoreService { return new MapSheetMngDto.DmlReturn("success", hstUidList.size() + "개 추론제외 업데이트 하였습니다."); } - /** - * 특정 파일명 + 여러 확장자가 모두 존재하는지 확인 - * - * @param rootDir 검색할 최상위 디렉토리 - * @param filename 파일명 (확장자 제외) - * @param extensions 확인할 확장자 배열 (예: {"tif", "tfw"}) - * @return 모든 확장자가 존재하면 true, 하나라도 없으면 false - */ - public static boolean allExtensionsExist(String rootDir, String filename, String... extensions) { - try (Stream paths = Files.walk(Paths.get(rootDir))) { - // 모든 파일명을 Set으로 저장 - Set fileNames = - paths - .filter(Files::isRegularFile) - .map(p -> p.getFileName().toString()) - .collect(Collectors.toSet()); - // 모든 확장자 파일 존재 여부 확인 - for (String ext : extensions) { - String target = filename + "." + ext; - if (!fileNames.contains(target)) { - return false; // 하나라도 없으면 false - } - } - - return true; // 모두 존재하면 true - - } catch (IOException e) { - throw new RuntimeException("File search error", e); - } - } - - public MapSheetMngDto.DmlReturn mngDataSave(@Valid MapSheetMngDto.AddReq addReq) { + public int mngDataSave(@Valid MapSheetMngDto.AddReq addReq) { MapSheetMngEntity entity = new MapSheetMngEntity(); entity.setMngYyyy(addReq.getMngYyyy()); @@ -234,10 +115,10 @@ public class MapSheetMngCoreService { mapSheetMngRepository.deleteByMngYyyyMngAll(addReq.getMngYyyy()); MapSheetMngEntity saved = mapSheetMngRepository.save(entity); - int hstCnt = mapSheetMngRepository.insertMapSheetOrgDataToMapSheetMngHst(saved.getMngYyyy()); + int hstCnt = mapSheetMngRepository.insertMapSheetOrgDataToMapSheetMngHst(saved.getMngYyyy(), saved.getMngPath()); mapSheetMngRepository.updateYearState(saved.getMngYyyy(), "DONE"); - return new MapSheetMngDto.DmlReturn("success", saved.getMngYyyy().toString()); + return hstCnt; } public List findHstUidToMapSheetFileList(Long hstUid) { @@ -248,37 +129,13 @@ public class MapSheetMngCoreService { mapSheetMngRepository.deleteByFileUidMngFile(fileUid); } - public MapSheetMngDto.DmlReturn updateByHstUidSyncCheckState(Long hstUid) { - - MapSheetMngDto.SyncCheckStateReqUpdateDto reqDto = - new MapSheetMngDto.SyncCheckStateReqUpdateDto(); - reqDto.setHstUid(hstUid); - - List filesDto = - mapSheetMngRepository.findHstUidToMapSheetFileList(hstUid); - for (MapSheetMngDto.MngFilesDto dto : filesDto) { - if (dto.getFileExt().equals("tif")) reqDto.setSyncCheckTifFileName(dto.getFileName()); - else if (dto.getFileExt().equals("tfw")) reqDto.setSyncCheckTfwFileName(dto.getFileName()); - reqDto.setFilePath(dto.getFilePath()); - } - - String fileState = "DONE"; - if (filesDto.size() > 2) fileState = "DONE"; - - reqDto.setSyncCheckState(fileState); - + public void updateByHstUidSyncCheckState(MapSheetMngDto.SyncCheckStateReqUpdateDto reqDto) { mapSheetMngRepository.updateMapSheetMngHstSyncCheckState(reqDto); - mapSheetMngRepository.updateByHstUidMngFileState(hstUid, fileState); - - return new MapSheetMngDto.DmlReturn("success", hstUid + " : 상태변경되었습니다."); } - public MapSheetMngDto.DmlReturn updateByFileUidFileState(Long fileUid, String fileState) { - + public void updateByFileUidFileState(Long fileUid, String fileState) { mapSheetMngRepository.updateByFileUidMngFileState(fileUid, fileState); - - return new MapSheetMngDto.DmlReturn("success", fileUid + " : 상태변경되었습니다."); } public void deleteByNotInFileUidMngFile(Long hstUid, List fileUids){ diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java index c49eda31..f23fdd18 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java @@ -19,7 +19,7 @@ public interface MapSheetMngRepositoryCustom { Optional findMapSheetMngHstInfo(Long hstUid); - int insertMapSheetOrgDataToMapSheetMngHst(int mngYyyy); + int insertMapSheetOrgDataToMapSheetMngHst(int mngYyyy, String mngPath); List findHstUidToMapSheetFileList(Long hstUid); @@ -54,7 +54,7 @@ public interface MapSheetMngRepositoryCustom { MapSheetMngDto.ErrorDataDto findMapSheetError(Long hstUid); - List findIdToMapSheetFileList(Long hstUid); + List findByHstUidMapSheetFileList(Long hstUid); MapSheetMngDto.MngFilesDto findByFileUidMapSheetFile(Long fileUid); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java index 5f826ea3..cd22a0f0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java @@ -448,10 +448,11 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport } @Override - public List findIdToMapSheetFileList(Long hstUid) { + public List findByHstUidMapSheetFileList(Long hstUid) { BooleanBuilder whereBuilder = new BooleanBuilder(); whereBuilder.and(mapSheetMngFileEntity.hstUid.eq(hstUid)); + whereBuilder.and(mapSheetMngFileEntity.fileDel.eq(false)); List foundContent = queryFactory @@ -725,13 +726,14 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport } @Override - public int insertMapSheetOrgDataToMapSheetMngHst(int mngYyyy) { + public int insertMapSheetOrgDataToMapSheetMngHst(int mngYyyy, String mngPath) { String sql = """ INSERT INTO tb_map_sheet_mng_hst ( mng_yyyy + ,map_sheet_path ,map_sheet_code ,map_sheet_num ,map_sheet_name @@ -741,14 +743,15 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport ,use_inference ) select - :mngYyyy as mng_yyyy - ,fid as map_sheet_code - ,mapidcd_no::INTEGER as map_sheet_num - ,mapid_nm as map_sheet_name - ,fid as map_sheet_code_src - ,5000 as scale_ratio - ,((mapidcd_no::INTEGER)/1000) as ref_map_sheet_num - ,use_inference + :mngYyyy as mng_yyyy, + :mngPath as map_sheet_path, + fid as map_sheet_code, + mapidcd_no as map_sheet_num, + mapid_nm as map_sheet_name, + fid as map_sheet_code_src, + 5000 as scale_ratio, + ((mapidcd_no::INTEGER)/1000) as ref_map_sheet_num, + use_inference from tb_map_inkx_5k """; @@ -756,6 +759,7 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport // Native Query 생성 및 실행 Query query = (Query) em.createNativeQuery(sql); query.setParameter("mngYyyy", mngYyyy); + query.setParameter("mngPath", mngPath); int exeCnt = query.executeUpdate(); // 실행 (영향받은 행의 개수 반환)