diff --git a/build.gradle b/build.gradle index 82198f5..21ab4f7 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,11 @@ dependencies { // GPKI JNI local library implementation files('lib/libgpkiapi_jni_1.5.jar') + // Database & MyBatis + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' + implementation 'org.mariadb.jdbc:mariadb-java-client:3.3.3' + // Configuration metadata annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' diff --git a/ddl/ibmsdb/seq_car_bass_matter_inqire.sql b/ddl/ibmsdb/seq_car_bass_matter_inqire.sql new file mode 100644 index 0000000..e9a1f80 --- /dev/null +++ b/ddl/ibmsdb/seq_car_bass_matter_inqire.sql @@ -0,0 +1,11 @@ +-- 자동차 기본 사항 조회 ID 시퀀스 +-- CBMI000000000001, CBMI000000000002, ... 형태로 생성 +CREATE SEQUENCE seq_car_bass_matter_inqire + START WITH 1 + INCREMENT BY 1 + MINVALUE 1 + MAXVALUE 9999999999 + CACHE 1000 + NOCYCLE; + +-- SELECT CONCAT('CBMI', LPAD(NEXTVAL(seq_car_bass_matter_inqire), 16, '0')); \ No newline at end of file diff --git a/ddl/ibmsdb/tb_car_bass_matter_inqire.sql b/ddl/ibmsdb/tb_car_bass_matter_inqire.sql new file mode 100644 index 0000000..d86fb32 --- /dev/null +++ b/ddl/ibmsdb/tb_car_bass_matter_inqire.sql @@ -0,0 +1,106 @@ +create table tb_car_bass_matter_inqire +( + CAR_BASS_MATTER_INQIRE varchar(20) not null comment '자동차 기본 사항 조회 ID' + primary key, + INFO_SYS_ID varchar(6) null comment '정보 시스템 ID', + INFO_SYS_IP varchar(23) null comment '정보 시스템 IP', + SIGUNGU_CODE varchar(5) null comment '시군구 코드', + CNTC_INFO_CODE varchar(10) null comment '연계 정보 코드', + CHARGER_ID varchar(15) null comment '담당자 ID', + CHARGER_IP varchar(23) null comment '담당자 IP', + CHARGER_NM varchar(75) null comment '담당자명', + DMND_LEVY_STDDE varchar(8) null comment '요청 부과 기준일', + DMND_INQIRE_SE_CODE varchar(1) null comment '요청 조회 구분 코드', + DMND_VHRNO varchar(30) null comment '요청 자동차등록번호', + DMND_VIN varchar(17) null comment '요청 차대번호', + CNTC_RESULT_CODE varchar(8) null comment '연계 결과 코드', + CNTC_RESULT_DTLS varchar(200) null comment '연계 결과 상세', + PRYE varchar(4) null comment '연식', + REGIST_DE varchar(8) null comment '등록일', + ERSR_REGIST_SE_CODE varchar(4) null comment '말소 등록 구분 코드', + ERSR_REGIST_SE_NM varchar(30) null comment '말소 등록 구분명', + ERSR_REGIST_DE varchar(8) null comment '말소 등록일', + REGIST_DETAIL_CODE varchar(3) null comment '등록 상세 코드', + DSPLVL varchar(6) null comment '배기량', + USE_STRNGHLD_LEGALDONG_CODE varchar(10) null comment '사용 본거지 법정동 코드', + USE_STRNGHLD_ADSTRD_CODE varchar(10) null comment '사용 본거지 행정동 코드', + USE_STRNGHLD_MNTN varchar(2) null comment '사용 본거지 산', + USE_STRNGHLD_LNBR varchar(4) null comment '사용 본거지 번지', + USE_STRNGHLD_HO varchar(4) null comment '사용 본거지 호', + USE_STRNGHLD_ADRES_NM varchar(300) null comment '사용 본거지 상세주소', + USE_STRNGHLD_ROAD_NM_CODE varchar(12) null comment '사용 본거지 도로명 코드', + USGSRHLD_UNDGRND_BULD_SE_CODE varchar(1) null comment '사용 본거지 지하 건물 구분 코드', + USE_STRNGHLD_BULD_MAIN_NO varchar(5) null comment '사용 본거지 건물 주요 번호', + USE_STRNGHLD_BULD_SUB_NO varchar(5) null comment '사용 본거지 건물 부 번호', + USGSRHLD_ADRES_FULL varchar(750) null comment '사용 본거지 전체주소', + MBER_SE_CODE varchar(2) null comment '대표소유자 회원 구분 코드', + MBER_SE_NO varchar(100) null comment '대표소유자 회원 번호', + TELNO varchar(20) null comment '대표소유자 전화번호', + OWNER_LEGALDONG_CODE varchar(10) null comment '소유자 법정동 코드', + OWNER_ADSTRD_CODE varchar(10) null comment '소유자 행정동 코드', + OWNER_MNTN varchar(2) null comment '소유자 산', + OWNER_LNBR varchar(4) null comment '소유자 번지', + OWNER_HO varchar(4) null comment '소유자 호', + OWNER_ADRES_NM varchar(300) null comment '소유자 상세주소', + OWNER_ROAD_NM_CODE varchar(12) null comment '소유자 도로명 코드', + OWNER_UNDGRND_BULD_SE_CODE varchar(1) null comment '소유자 지하건물 구분 코드', + OWNER_BULD_MAIN_NO varchar(5) null comment '소유자 건물 주요 번호', + OWNER_BULD_SUB_NO varchar(5) null comment '소유자 건물 부 번호', + OWNR_WHOLADDR varchar(750) null comment '소유자 전체주소', + AFTR_VHRNO varchar(30) null comment '신 차량번호', + USE_FUEL_CODE varchar(1) null comment '사용 연료 코드', + PRPOS_SE_CODE varchar(2) null comment '용도 구분 코드', + MTRS_FOM_NM varchar(75) null comment '원동기 형식명', + FRNT_VHRNO varchar(30) null comment '이전 차량번호', + VHCLNO varchar(30) null comment '차량번호', + VIN varchar(17) null comment '차대번호', + CNM varchar(75) null comment '차명', + VHCLE_TOT_WT varchar(6) null comment '차량 총 중량', + CAAG_ENDDE varchar(8) null comment '차령 만료일자', + CHANGE_DE varchar(8) null comment '차번호 변경시기', + VHCTY_ASORT_CODE varchar(1) null comment '차종 종별 코드', + VHCTY_TY_CODE varchar(1) null comment '차종 유형 코드', + VHCTY_SE_CODE varchar(1) null comment '차종 분류 코드', + MXMM_LDG varchar(10) null comment '최대 적재량', + VHCTY_ASORT_NM varchar(150) null comment '차종 종별명', + VHCTY_TY_NM varchar(150) null comment '차종 유형명', + VHCTY_SE_NM varchar(150) null comment '차종 분류명', + FRST_REGIST_DE varchar(8) null comment '최초 등록일', + FOM_NM varchar(75) null comment '형식', + ACQS_DE varchar(8) null comment '취득 일자', + ACQS_END_DE varchar(8) null comment '취득 종료일자', + YBL_MD varchar(8) null comment '제작 년월일', + TRANSR_REGIST_DE varchar(8) null comment '이전 등록일', + SPCF_REGIST_STTUS_CODE varchar(6) null comment '제원 등록 상태 코드', + COLOR_NM varchar(75) null comment '색상명', + MRTG_CO varchar(9) null comment '저당수', + SEIZR_CO varchar(9) null comment '압류건수', + STMD_CO varchar(9) null comment '구조변경수', + NMPL_CSDY_AT varchar(1) null comment '번호판 영치 여부', + NMPL_CSDY_REMNR_DE varchar(8) null comment '번호판 영치 최고일', + ORIGIN_SE_CODE varchar(1) null comment '출처 구분 코드', + NMPL_STNDRD_CODE varchar(1) null comment '번호판 규격 코드', + ACQS_AMOUNT varchar(18) null comment '취득 금액', + INSPT_VALID_PD_BGNDE varchar(8) null comment '검사 유효 기간 시작일', + INSPT_VALID_PD_ENDDE varchar(8) null comment '검사 유효 기간 종료일', + USE_STRNGHLD_GRC_CODE varchar(4) null comment '사용 본거지 관청 코드', + TKCAR_PSCAP_CO varchar(3) null comment '승차정원수', + SPMNNO varchar(17) null comment '제원관리번호', + TRVL_DSTNC varchar(10) null comment '주행거리', + FRST_REGIST_RQRCNO varchar(20) null comment '최초 등록 접수번호', + VLNT_ERSR_PRVNTC_NTICE_DE varchar(8) null comment '예고통지일', + REGIST_INSTT_NM varchar(150) null comment '등록 기관명', + PROCESS_IMPRTY_RESN_CODE varchar(2) null comment '처리 불가 사유 코드', + PROCESS_IMPRTY_RESN_DTLS varchar(75) null comment '처리 불가 사유 명세', + CBD_LT varchar(10) null comment '차체 길이', + CBD_BT varchar(10) null comment '차체 너비', + CBD_HG varchar(10) null comment '차체 높이', + FRST_MXMM_LDG varchar(10) null comment '최초 최대 적재량', + FUEL_CNSMP_RT varchar(5) null comment '연료 소비율', + ELCTY_CMPND_FUEL_CNSMP_RT varchar(5) null comment '전기 복합 연료 소비율', + REG_DT datetime null comment '등록 일시', + RGTR varchar(11) null comment '등록자', + MBER_NM varchar(75) null comment '대표소유자 성명' +) + comment '자동차 기본 사항 조회'; + diff --git a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java index 5e77dd7..eed35c3 100644 --- a/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java +++ b/src/main/java/com/vmis/interfaceapp/client/GovernmentApiClient.java @@ -6,10 +6,12 @@ import com.vmis.interfaceapp.config.properties.VmisProperties; import com.vmis.interfaceapp.gpki.GpkiService; import com.vmis.interfaceapp.model.basic.BasicRequest; import com.vmis.interfaceapp.model.basic.BasicResponse; +import com.vmis.interfaceapp.model.basic.CarBassMatterInqireVO; import com.vmis.interfaceapp.model.common.Envelope; import com.vmis.interfaceapp.model.ledger.LedgerRequest; import com.vmis.interfaceapp.model.ledger.LedgerResponse; import com.vmis.interfaceapp.util.TxIdUtil; +import lombok.RequiredArgsConstructor; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.web.client.HttpStatusCodeException; @@ -56,6 +58,7 @@ import java.nio.charset.StandardCharsets; * @see VmisProperties */ @Slf4j +@RequiredArgsConstructor @Component public class GovernmentApiClient { @@ -122,6 +125,13 @@ public class GovernmentApiClient { */ private final ObjectMapper objectMapper; + /** + * 자동차 기본 사항 조회 로그 서비스 + * + *
API 호출 정보를 DB에 로그성으로 저장합니다.
+ */ + private final com.vmis.interfaceapp.service.CarBassMatterInqireService carBassMatterInqireService; + /** * 서비스 타입 열거형 * @@ -156,134 +166,6 @@ public class GovernmentApiClient { */ LEDGER } - /** - * 생성자를 통한 의존성 주입 - * - *Spring의 생성자 주입 방식을 사용하여 필요한 모든 의존성을 주입받습니다. - * - * @param restTemplate HTTP 통신을 위한 RestTemplate 객체 - * @param props VMIS 애플리케이션 설정 속성 - * @param gpkiService GPKI 암호화/복호화 서비스 - * @param objectMapper JSON 직렬화/역직렬화를 위한 ObjectMapper - * @Component 어노테이션과 함께 사용되어 자동으로 Spring Bean으로 등록됩니다.
이 메서드는 JSON 문자열을 직접 받아 정부 API를 호출하는 저수준(Low-level) 메서드입니다. - * 타입 안전성이 필요한 경우 {@link #callModel} 메서드를 사용하는 것이 권장됩니다.
- * - *
* BasicRequest request = new BasicRequest();
@@ -435,9 +322,34 @@ public class GovernmentApiClient {
* @return ResponseEntity<Envelope<BasicResponse>> 조회 결과를 담은 응답
*/
public ResponseEntity> callBasic(Envelope envelope) {
- // TypeReference를 사용하여 제네릭 타입 정보 전달
- // 익명 클래스를 생성하여 타입 소거(Type Erasure) 문제 해결
- return callModel(ServiceType.BASIC, envelope, new TypeReference>(){});
+ String generatedId = null;
+
+ try {
+ // 1. 요청 정보 DB 저장 (첫 번째 요청만 저장)
+ if (envelope.getData() != null && !envelope.getData().isEmpty()) {
+ com.vmis.interfaceapp.model.basic.BasicRequest request = envelope.getData().get(0);
+ generatedId = saveRequestLog(request);
+ log.info("[BASIC-REQ-LOG] 요청 정보 저장 완료 - ID: {}, 차량번호: {}", generatedId, request.getVhrno());
+ }
+
+ // 2. 정부 API 호출
+ ResponseEntity> response = callModel(ServiceType.BASIC, envelope, new TypeReference>(){});
+
+ // 3. 응답 정보 DB 업데이트
+ if (generatedId != null && response.getBody() != null) {
+ updateResponseLog(generatedId, response.getBody());
+ log.info("[BASIC-RES-LOG] 응답 정보 저장 완료 - ID: {}", generatedId);
+ }
+
+ return response;
+
+ } catch (Exception e) {
+ // 4. 에러 발생 시 에러 정보 DB 업데이트
+ if (generatedId != null) {
+ updateErrorLog(generatedId, e);
+ }
+ throw e;
+ }
}
/**
@@ -744,4 +656,175 @@ public class GovernmentApiClient {
throw new RuntimeException("GPKI 복호화 실패", e);
}
}
+
+ /**
+ * 요청 정보를 DB에 저장
+ *
+ * @param request 요청 정보
+ * @return 생성된 ID
+ */
+ private String saveRequestLog(com.vmis.interfaceapp.model.basic.BasicRequest request) {
+ CarBassMatterInqireVO logEntity = CarBassMatterInqireVO.builder()
+ .infoSysId(request.getInfoSysId())
+ .infoSysIp(request.getInfoSysIp())
+ .sigunguCode(request.getSigunguCode())
+ .cntcInfoCode(request.getCntcInfoCode())
+ .chargerId(request.getChargerId())
+ .chargerIp(request.getChargerIp())
+ .chargerNm(request.getChargerNm())
+ .dmndLevyStdde(request.getLevyStdde())
+ .dmndInqireSeCode(request.getInqireSeCode())
+ .dmndVhrno(request.getVhrno())
+ .dmndVin(request.getVin())
+ .rgtr("SYSTEM")
+ .build();
+
+ return carBassMatterInqireService.createInitialRequest(logEntity);
+ }
+
+ /**
+ * 응답 정보를 DB에 업데이트
+ *
+ * @param id 저장된 ID
+ * @param envelope 응답 정보
+ */
+ private void updateResponseLog(String id, Envelope envelope) {
+ com.vmis.interfaceapp.model.basic.BasicResponse response = envelope.getData() != null && !envelope.getData().isEmpty()
+ ? envelope.getData().get(0)
+ : null;
+
+ if (response == null) {
+ log.warn("[BASIC-RES-LOG] 응답 데이터가 없습니다 - ID: {}", id);
+ return;
+ }
+
+ // Builder 패턴으로 응답 정보 매핑
+ CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder = CarBassMatterInqireVO.builder()
+ .carBassMatterInqire(id)
+ .cntcResultCode(response.getCntcResultCode())
+ .cntcResultDtls(response.getCntcResultDtls());
+
+ // record가 있으면 첫 번째 record의 정보를 매핑
+ if (response.getRecord() != null && !response.getRecord().isEmpty()) {
+ com.vmis.interfaceapp.model.basic.BasicResponse.Record record = response.getRecord().get(0);
+ mapRecordToEntity(builder, record);
+ }
+
+ carBassMatterInqireService.updateResponse(builder.build());
+ }
+
+ /**
+ * Record 정보를 Entity에 매핑
+ *
+ * @param builder Entity Builder
+ * @param record Record 정보
+ */
+ private void mapRecordToEntity(CarBassMatterInqireVO.CarBassMatterInqireVOBuilder builder, com.vmis.interfaceapp.model.basic.BasicResponse.Record record) {
+ builder
+ .prye(record.getPrye())
+ .registDe(record.getRegistDe())
+ .ersrRegistSeCode(record.getErsrRegistSeCode())
+ .ersrRegistSeNm(record.getErsrRegistSeNm())
+ .ersrRegistDe(record.getErsrRegistDe())
+ .registDetailCode(record.getRegistDetailCode())
+ .dsplvl(record.getDsplvl())
+ .useStrnghldLegaldongCode(record.getUseStrnghldLegaldongCode())
+ .useStrnghldAdstrdCode(record.getUseStrnghldAdstrdCode())
+ .useStrnghldMntn(record.getUseStrnghldMntn())
+ .useStrnghldLnbr(record.getUseStrnghldLnbr())
+ .useStrnghldHo(record.getUseStrnghldHo())
+ .useStrnghldAdresNm(record.getUseStrnghldAdresNm())
+ .useStrnghldRoadNmCode(record.getUseStrnghldRoadNmCode())
+ .usgsrhldUndgrndBuldSeCode(record.getUsgsrhldUndgrndBuldSeCode())
+ .useStrnghldBuldMainNo(record.getUseStrnghldBuldMainNo())
+ .useStrnghldBuldSubNo(record.getUseStrnghldBuldSubNo())
+ .usgsrhldAdresFull(record.getUsgsrhldAdresFull())
+ .mberSeCode(record.getMberSeCode())
+ .mberSeNo(record.getMberSeNo())
+ .mberNm(record.getMberNm())
+ .telno(record.getTelno())
+ .ownerLegaldongCode(record.getOwnerLegaldongCode())
+ .ownerAdstrdCode(record.getOwnerAdstrdCode())
+ .ownerMntn(record.getOwnerMntn())
+ .ownerLnbr(record.getOwnerLnbr())
+ .ownerHo(record.getOwnerHo())
+ .ownerAdresNm(record.getOwnerAdresNm())
+ .ownerRoadNmCode(record.getOwnerRoadNmCode())
+ .ownerUndgrndBuldSeCode(record.getOwnerUndgrndBuldSeCode())
+ .ownerBuldMainNo(record.getOwnerBuldMainNo())
+ .ownerBuldSubNo(record.getOwnerBuldSubNo())
+ .ownrWholaddr(record.getOwnerAdresFull())
+ .aftrVhrno(record.getAftrVhrno())
+ .useFuelCode(record.getUseFuelCode())
+ .prposSeCode(record.getPrposSeCode())
+ .mtrsFomNm(record.getMtrsFomNm())
+ .frntVhrno(record.getFrntVhrno())
+ .vhclno(record.getVhrno())
+ .vin(record.getVin())
+ .cnm(record.getCnm())
+ .vhcleTotWt(record.getVhcleTotWt())
+ .caagEndde(record.getCaagEndde())
+ .changeDe(record.getChangeDe())
+ .vhctyAsortCode(record.getVhctyAsortCode())
+ .vhctyTyCode(record.getVhctyTyCode())
+ .vhctySeCode(record.getVhctySeCode())
+ .mxmmLdg(record.getMxmmLdg())
+ .vhctyAsortNm(record.getVhctyAsortNm())
+ .vhctyTyNm(record.getVhctyTyNm())
+ .vhctySeNm(record.getVhctySeNm())
+ .frstRegistDe(record.getFrstRegistDe())
+ .fomNm(record.getFomNm())
+ .acqsDe(record.getAcqsDe())
+ .acqsEndDe(record.getAcqsEndDe())
+ .yblMd(record.getYblMd())
+ .transrRegistDe(record.getTransrRegistDe())
+ .spcfRegistSttusCode(record.getSpcfRegistSttusCode())
+ .colorNm(record.getColorNm())
+ .mrtgCo(record.getMrtgCo())
+ .seizrCo(record.getSeizrCo())
+ .stmdCo(record.getStmdCo())
+ .nmplCsdyAt(record.getNmplCsdyAt())
+ .nmplCsdyRemnrDe(record.getNmplCsdyRemnrDe())
+ .originSeCode(record.getOriginSeCode())
+ .nmplStndrdCode(record.getNmplStndrdCode())
+ .acqsAmount(record.getAcqsAmount())
+ .insptValidPdBgnde(record.getInsptValidPdBgnde())
+ .insptValidPdEndde(record.getInsptValidPdEndde())
+ .useStrnghldGrcCode(record.getUseStrnghldGrcCode())
+ .tkcarPscapCo(record.getTkcarPscapCo())
+ .spmnno(record.getSpmnno())
+ .trvlDstnc(record.getTrvlDstnc())
+ .frstRegistRqrcno(record.getFrstRegistRqrcno())
+ .vlntErsrPrvntcNticeDe(record.getVlntErsrPrvntcNticeDe())
+ .registInsttNm(record.getRegistInsttNm())
+ .processImprtyResnCode(record.getProcessImprtyResnCode())
+ .processImprtyResnDtls(record.getProcessImprtyResnDtls())
+ .cbdLt(record.getCbdLt())
+ .cbdBt(record.getCbdBt())
+ .cbdHg(record.getCbdHg())
+ .frstMxmmLdg(record.getFrstMxmmLdg())
+ .fuelCnsmpRt(record.getFuelCnsmpRt())
+ .elctyCmpndFuelCnsmpRt(record.getElctyCmpndFuelCnsmpRt());
+ }
+
+ /**
+ * 에러 정보를 DB에 업데이트
+ *
+ * @param id 저장된 ID
+ * @param exception 발생한 예외
+ */
+ private void updateErrorLog(String id, Exception exception) {
+ try {
+ CarBassMatterInqireVO errorLog = CarBassMatterInqireVO.builder()
+ .carBassMatterInqire(id)
+ .cntcResultCode("99")
+ .cntcResultDtls("오류: " + exception.getMessage())
+ .build();
+
+ carBassMatterInqireService.updateResponse(errorLog);
+ log.error("[BASIC-ERR-LOG] API 호출 에러 정보 저장 완료 - ID: {}", id, exception);
+ } catch (Exception e) {
+ log.error("[BASIC-ERR-LOG] 에러 로그 저장 실패 - ID: {}", id, e);
+ }
+ }
}
diff --git a/src/main/java/com/vmis/interfaceapp/config/DatabaseConfig.java b/src/main/java/com/vmis/interfaceapp/config/DatabaseConfig.java
new file mode 100644
index 0000000..d6a1d66
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/config/DatabaseConfig.java
@@ -0,0 +1,57 @@
+package com.vmis.interfaceapp.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+
+/**
+ * 데이터베이스 및 트랜잭션 설정
+ *
+ * 이 클래스는 데이터베이스 연결과 트랜잭션 관리를 위한 설정을 제공합니다.
+ * Spring Boot의 자동 설정을 활용하되, 명시적인 트랜잭션 관리를 위해
+ * TransactionManager를 직접 설정합니다.
+ *
+ *
+ * - DataSource: application.yml에서 자동 설정
+ * - SqlSessionFactory: MyBatis Spring Boot Starter가 자동 생성
+ * - TransactionManager: 명시적으로 설정하여 트랜잭션 관리
+ * - MapperScan: com.vmis.interfaceapp.mapper 패키지의 Mapper 인터페이스 자동 스캔
+ *
+ */
+@Configuration
+@EnableTransactionManagement
+@MapperScan("com.vmis.interfaceapp.mapper")
+public class DatabaseConfig {
+
+ /**
+ * 트랜잭션 관리자를 설정합니다.
+ *
+ * DataSourceTransactionManager는 JDBC 기반의 트랜잭션을 관리합니다.
+ * @Transactional 어노테이션을 사용하여 선언적 트랜잭션 관리가 가능합니다.
+ *
+ * 트랜잭션 전파(Propagation), 격리 수준(Isolation), 타임아웃 등의
+ * 세부 설정은 @Transactional 어노테이션의 속성으로 지정할 수 있습니다.
+ *
+ * 예제:
+ *
+ * {@code
+ * @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
+ * public void saveData() {
+ * // 트랜잭션 처리가 필요한 로직
+ * }
+ * }
+ *
+ *
+ * @param dataSource Spring Boot가 자동 생성한 DataSource 빈
+ * @return PlatformTransactionManager 트랜잭션 관리자 인스턴스
+ */
+ @Bean
+ public PlatformTransactionManager transactionManager(DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
+}
diff --git a/src/main/java/com/vmis/interfaceapp/config/Globals.java b/src/main/java/com/vmis/interfaceapp/config/Globals.java
new file mode 100644
index 0000000..d175beb
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/config/Globals.java
@@ -0,0 +1,39 @@
+package com.vmis.interfaceapp.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 전역 상수 및 설정값을 관리하는 클래스
+ *
+ * 이 클래스는 애플리케이션 전반에서 사용되는 전역 설정값을 제공합니다.
+ * Spring의 @Value를 통해 application.yml의 설정값을 주입받아 사용합니다.
+ */
+@Component
+public class Globals {
+
+ /**
+ * 데이터베이스 타입 (예: mariadb, oracle, mysql 등)
+ *
+ * MyBatis Mapper XML 파일 선택 시 사용됩니다.
+ * mapper-locations: classpath:mybatis/mapper/**\/*_${Globals.DbType}.xml
+ *
+ * 예시:
+ *
+ * - DbType = "mariadb" → user_mariadb.xml 매핑
+ * - DbType = "oracle" → user_oracle.xml 매핑
+ *
+ *
+ */
+ public static String DbType;
+
+ /**
+ * application.yml에서 Globals.DbType 값을 주입합니다.
+ *
+ * @param dbType 데이터베이스 타입 (기본값: mariadb)
+ */
+ @Value("${Globals.DbType:mariadb}")
+ public void setDbType(String dbType) {
+ Globals.DbType = dbType;
+ }
+}
diff --git a/src/main/java/com/vmis/interfaceapp/mapper/CarBassMatterInqireMapper.java b/src/main/java/com/vmis/interfaceapp/mapper/CarBassMatterInqireMapper.java
new file mode 100644
index 0000000..e192e25
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/mapper/CarBassMatterInqireMapper.java
@@ -0,0 +1,54 @@
+package com.vmis.interfaceapp.mapper;
+
+import com.vmis.interfaceapp.model.basic.CarBassMatterInqireVO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 자동차 기본 사항 조회 Mapper
+ *
+ * API 호출 정보를 관리하는 Mapper 인터페이스입니다.
+ *
+ * - 최초 요청 시: insertCarBassMatterInqire() 호출
+ * - 결과 수신 시: updateCarBassMatterInqire() 호출
+ *
+ */
+@Mapper
+public interface CarBassMatterInqireMapper {
+
+ /**
+ * 시퀀스로 새로운 자동차 기본 사항 조회 ID를 생성합니다.
+ *
+ * 형식: CBMI000000000001
+ *
+ * @return 생성된 ID
+ */
+ String selectNextCarBassMatterInqireId();
+
+ /**
+ * 최초 API 요청 정보를 등록합니다.
+ *
+ * 요청 시점의 정보만 저장하며, 응답 정보는 null 상태입니다.
+ *
+ * @param carBassMatterInqireVO 요청 정보
+ * @return 등록된 행 수
+ */
+ int insertCarBassMatterInqire(CarBassMatterInqireVO carBassMatterInqireVO);
+
+ /**
+ * API 응답 결과를 업데이트합니다.
+ *
+ * 응답 받은 데이터를 기존 레코드에 업데이트합니다.
+ *
+ * @param carBassMatterInqireVO 응답 정보 (carBassMatterInqire 필드는 필수)
+ * @return 업데이트된 행 수
+ */
+ int updateCarBassMatterInqire(CarBassMatterInqireVO carBassMatterInqireVO);
+
+ /**
+ * ID로 조회 정보를 조회합니다.
+ *
+ * @param carBassMatterInqire 자동차 기본 사항 조회 ID
+ * @return 조회된 정보
+ */
+ CarBassMatterInqireVO selectCarBassMatterInqireById(String carBassMatterInqire);
+}
diff --git a/src/main/java/com/vmis/interfaceapp/mapper/SampleMapper.java b/src/main/java/com/vmis/interfaceapp/mapper/SampleMapper.java
new file mode 100644
index 0000000..528aa2c
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/mapper/SampleMapper.java
@@ -0,0 +1,26 @@
+package com.vmis.interfaceapp.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 샘플 MyBatis Mapper 인터페이스
+ *
+ * 이 인터페이스는 MyBatis 설정 테스트 및 예제 용도입니다.
+ * 실제 프로젝트에서는 비즈니스 요구사항에 맞는 Mapper를 작성하세요.
+ *
+ * @Mapper 어노테이션을 사용하면 Spring이 자동으로 구현체를 생성합니다.
+ * XML 파일의 namespace와 이 인터페이스의 경로가 일치해야 합니다.
+ */
+@Mapper
+public interface SampleMapper {
+
+ /**
+ * 데이터베이스 연결 테스트용 쿼리
+ *
+ * 현재 시간을 조회하여 데이터베이스 연결이 정상적으로
+ * 작동하는지 확인할 수 있습니다.
+ *
+ * @return 현재 시간 문자열
+ */
+ String selectCurrentTime();
+}
diff --git a/src/main/java/com/vmis/interfaceapp/model/basic/CarBassMatterInqireVO.java b/src/main/java/com/vmis/interfaceapp/model/basic/CarBassMatterInqireVO.java
new file mode 100644
index 0000000..53e7838
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/model/basic/CarBassMatterInqireVO.java
@@ -0,0 +1,524 @@
+package com.vmis.interfaceapp.model.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 자동차 기본 사항 조회 엔티티
+ *
+ * API 호출 정보를 저장하는 테이블 매핑 클래스입니다.
+ * 최초 요청 시 INSERT, 결과 수신 시 UPDATE 형태로 사용됩니다.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CarBassMatterInqireVO {
+
+ /**
+ * 자동차 기본 사항 조회 ID (PK)
+ * 형식: CBMI000000000001
+ */
+ private String carBassMatterInqire;
+
+ // ===== 요청 정보 =====
+ /**
+ * 정보 시스템 ID
+ */
+ private String infoSysId;
+
+ /**
+ * 정보 시스템 IP
+ */
+ private String infoSysIp;
+
+ /**
+ * 시군구 코드
+ */
+ private String sigunguCode;
+
+ /**
+ * 연계 정보 코드
+ */
+ private String cntcInfoCode;
+
+ /**
+ * 담당자 ID
+ */
+ private String chargerId;
+
+ /**
+ * 담당자 IP
+ */
+ private String chargerIp;
+
+ /**
+ * 담당자명
+ */
+ private String chargerNm;
+
+ /**
+ * 요청 부과 기준일
+ */
+ private String dmndLevyStdde;
+
+ /**
+ * 요청 조회 구분 코드
+ */
+ private String dmndInqireSeCode;
+
+ /**
+ * 요청 자동차등록번호
+ */
+ private String dmndVhrno;
+
+ /**
+ * 요청 차대번호
+ */
+ private String dmndVin;
+
+ // ===== 응답 정보 (결과 수신 시 UPDATE) =====
+ /**
+ * 연계 결과 코드
+ */
+ private String cntcResultCode;
+
+ /**
+ * 연계 결과 상세
+ */
+ private String cntcResultDtls;
+
+ /**
+ * 연식
+ */
+ private String prye;
+
+ /**
+ * 등록일
+ */
+ private String registDe;
+
+ /**
+ * 말소 등록 구분 코드
+ */
+ private String ersrRegistSeCode;
+
+ /**
+ * 말소 등록 구분명
+ */
+ private String ersrRegistSeNm;
+
+ /**
+ * 말소 등록일
+ */
+ private String ersrRegistDe;
+
+ /**
+ * 등록 상세 코드
+ */
+ private String registDetailCode;
+
+ /**
+ * 배기량
+ */
+ private String dsplvl;
+
+ /**
+ * 사용 본거지 법정동 코드
+ */
+ private String useStrnghldLegaldongCode;
+
+ /**
+ * 사용 본거지 행정동 코드
+ */
+ private String useStrnghldAdstrdCode;
+
+ /**
+ * 사용 본거지 산
+ */
+ private String useStrnghldMntn;
+
+ /**
+ * 사용 본거지 번지
+ */
+ private String useStrnghldLnbr;
+
+ /**
+ * 사용 본거지 호
+ */
+ private String useStrnghldHo;
+
+ /**
+ * 사용 본거지 상세주소
+ */
+ private String useStrnghldAdresNm;
+
+ /**
+ * 사용 본거지 도로명 코드
+ */
+ private String useStrnghldRoadNmCode;
+
+ /**
+ * 사용 본거지 지하 건물 구분 코드
+ */
+ private String usgsrhldUndgrndBuldSeCode;
+
+ /**
+ * 사용 본거지 건물 주요 번호
+ */
+ private String useStrnghldBuldMainNo;
+
+ /**
+ * 사용 본거지 건물 부 번호
+ */
+ private String useStrnghldBuldSubNo;
+
+ /**
+ * 사용 본거지 전체주소
+ */
+ private String usgsrhldAdresFull;
+
+ /**
+ * 대표소유자 회원 구분 코드
+ */
+ private String mberSeCode;
+
+ /**
+ * 대표소유자 회원 번호
+ */
+ private String mberSeNo;
+
+ /**
+ * 대표소유자 전화번호
+ */
+ private String telno;
+
+ /**
+ * 소유자 법정동 코드
+ */
+ private String ownerLegaldongCode;
+
+ /**
+ * 소유자 행정동 코드
+ */
+ private String ownerAdstrdCode;
+
+ /**
+ * 소유자 산
+ */
+ private String ownerMntn;
+
+ /**
+ * 소유자 번지
+ */
+ private String ownerLnbr;
+
+ /**
+ * 소유자 호
+ */
+ private String ownerHo;
+
+ /**
+ * 소유자 상세주소
+ */
+ private String ownerAdresNm;
+
+ /**
+ * 소유자 도로명 코드
+ */
+ private String ownerRoadNmCode;
+
+ /**
+ * 소유자 지하건물 구분 코드
+ */
+ private String ownerUndgrndBuldSeCode;
+
+ /**
+ * 소유자 건물 주요 번호
+ */
+ private String ownerBuldMainNo;
+
+ /**
+ * 소유자 건물 부 번호
+ */
+ private String ownerBuldSubNo;
+
+ /**
+ * 소유자 전체주소
+ */
+ private String ownrWholaddr;
+
+ /**
+ * 신 차량번호
+ */
+ private String aftrVhrno;
+
+ /**
+ * 사용 연료 코드
+ */
+ private String useFuelCode;
+
+ /**
+ * 용도 구분 코드
+ */
+ private String prposSeCode;
+
+ /**
+ * 원동기 형식명
+ */
+ private String mtrsFomNm;
+
+ /**
+ * 이전 차량번호
+ */
+ private String frntVhrno;
+
+ /**
+ * 차량번호
+ */
+ private String vhclno;
+
+ /**
+ * 차대번호
+ */
+ private String vin;
+
+ /**
+ * 차명
+ */
+ private String cnm;
+
+ /**
+ * 차량 총 중량
+ */
+ private String vhcleTotWt;
+
+ /**
+ * 차령 만료일자
+ */
+ private String caagEndde;
+
+ /**
+ * 차번호 변경시기
+ */
+ private String changeDe;
+
+ /**
+ * 차종 종별 코드
+ */
+ private String vhctyAsortCode;
+
+ /**
+ * 차종 유형 코드
+ */
+ private String vhctyTyCode;
+
+ /**
+ * 차종 분류 코드
+ */
+ private String vhctySeCode;
+
+ /**
+ * 최대 적재량
+ */
+ private String mxmmLdg;
+
+ /**
+ * 차종 종별명
+ */
+ private String vhctyAsortNm;
+
+ /**
+ * 차종 유형명
+ */
+ private String vhctyTyNm;
+
+ /**
+ * 차종 분류명
+ */
+ private String vhctySeNm;
+
+ /**
+ * 최초 등록일
+ */
+ private String frstRegistDe;
+
+ /**
+ * 형식
+ */
+ private String fomNm;
+
+ /**
+ * 취득 일자
+ */
+ private String acqsDe;
+
+ /**
+ * 취득 종료일자
+ */
+ private String acqsEndDe;
+
+ /**
+ * 제작 년월일
+ */
+ private String yblMd;
+
+ /**
+ * 이전 등록일
+ */
+ private String transrRegistDe;
+
+ /**
+ * 제원 등록 상태 코드
+ */
+ private String spcfRegistSttusCode;
+
+ /**
+ * 색상명
+ */
+ private String colorNm;
+
+ /**
+ * 저당수
+ */
+ private String mrtgCo;
+
+ /**
+ * 압류건수
+ */
+ private String seizrCo;
+
+ /**
+ * 구조변경수
+ */
+ private String stmdCo;
+
+ /**
+ * 번호판 영치 여부
+ */
+ private String nmplCsdyAt;
+
+ /**
+ * 번호판 영치 최고일
+ */
+ private String nmplCsdyRemnrDe;
+
+ /**
+ * 출처 구분 코드
+ */
+ private String originSeCode;
+
+ /**
+ * 번호판 규격 코드
+ */
+ private String nmplStndrdCode;
+
+ /**
+ * 취득 금액
+ */
+ private String acqsAmount;
+
+ /**
+ * 검사 유효 기간 시작일
+ */
+ private String insptValidPdBgnde;
+
+ /**
+ * 검사 유효 기간 종료일
+ */
+ private String insptValidPdEndde;
+
+ /**
+ * 사용 본거지 관청 코드
+ */
+ private String useStrnghldGrcCode;
+
+ /**
+ * 승차정원수
+ */
+ private String tkcarPscapCo;
+
+ /**
+ * 제원관리번호
+ */
+ private String spmnno;
+
+ /**
+ * 주행거리
+ */
+ private String trvlDstnc;
+
+ /**
+ * 최초 등록 접수번호
+ */
+ private String frstRegistRqrcno;
+
+ /**
+ * 예고통지일
+ */
+ private String vlntErsrPrvntcNticeDe;
+
+ /**
+ * 등록 기관명
+ */
+ private String registInsttNm;
+
+ /**
+ * 처리 불가 사유 코드
+ */
+ private String processImprtyResnCode;
+
+ /**
+ * 처리 불가 사유 명세
+ */
+ private String processImprtyResnDtls;
+
+ /**
+ * 차체 길이
+ */
+ private String cbdLt;
+
+ /**
+ * 차체 너비
+ */
+ private String cbdBt;
+
+ /**
+ * 차체 높이
+ */
+ private String cbdHg;
+
+ /**
+ * 최초 최대 적재량
+ */
+ private String frstMxmmLdg;
+
+ /**
+ * 연료 소비율
+ */
+ private String fuelCnsmpRt;
+
+ /**
+ * 전기 복합 연료 소비율
+ */
+ private String elctyCmpndFuelCnsmpRt;
+
+ /**
+ * 등록 일시
+ */
+ private LocalDateTime regDt;
+
+ /**
+ * 등록자
+ */
+ private String rgtr;
+
+ /**
+ * 대표소유자 성명
+ */
+ private String mberNm;
+}
diff --git a/src/main/java/com/vmis/interfaceapp/service/CarBassMatterInqireService.java b/src/main/java/com/vmis/interfaceapp/service/CarBassMatterInqireService.java
new file mode 100644
index 0000000..f69f410
--- /dev/null
+++ b/src/main/java/com/vmis/interfaceapp/service/CarBassMatterInqireService.java
@@ -0,0 +1,126 @@
+package com.vmis.interfaceapp.service;
+
+import com.vmis.interfaceapp.mapper.CarBassMatterInqireMapper;
+import com.vmis.interfaceapp.model.basic.CarBassMatterInqireVO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 자동차 기본 사항 조회 서비스
+ *
+ * API 호출 정보를 관리하는 서비스 클래스입니다.
+ *
+ * - 최초 요청: createInitialRequest() - 시퀀스로 ID 생성 후 INSERT
+ * - 결과 업데이트: updateResponse() - 응답 데이터 UPDATE
+ *
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class CarBassMatterInqireService {
+
+ private final CarBassMatterInqireMapper carBassMatterInqireMapper;
+
+ /**
+ * 최초 API 요청 정보를 등록합니다.
+ *
+ * 시퀀스로 새로운 ID를 생성하여 요청 정보를 저장합니다.
+ * 트랜잭션 내에서 실행되며, 예외 발생 시 롤백됩니다.
+ *
+ * 사용 예시:
+ *
+ * {@code
+ * CarBassMatterInqire request = CarBassMatterInqire.builder()
+ * .infoSysId("41-345")
+ * .infoSysIp("105.19.10.135")
+ * .sigunguCode("41460")
+ * .cntcInfoCode("AC1_FD11_01")
+ * .dmndVhrno("12가3456")
+ * .rgtr("SYSTEM")
+ * .build();
+ *
+ * String generatedId = service.createInitialRequest(request);
+ * log.info("생성된 ID: {}", generatedId);
+ * }
+ *
+ *
+ * @param request 요청 정보 (ID 제외)
+ * @return 생성된 자동차 기본 사항 조회 ID (CBMI000000000001 형식)
+ * @throws RuntimeException 저장 실패 시
+ */
+ @Transactional
+ public String createInitialRequest(CarBassMatterInqireVO request) {
+ // 시퀀스로 새로운 ID 생성
+ String generatedId = carBassMatterInqireMapper.selectNextCarBassMatterInqireId();
+ log.debug("생성된 자동차 기본 사항 조회 ID: {}", generatedId);
+
+ // 생성된 ID 설정
+ request.setCarBassMatterInqire(generatedId);
+
+ // INSERT
+ int result = carBassMatterInqireMapper.insertCarBassMatterInqire(request);
+ if (result != 1) {
+ throw new RuntimeException("자동차 기본 사항 조회 정보 등록 실패");
+ }
+
+ log.info("자동차 기본 사항 조회 정보 등록 완료 - ID: {}, 차량번호: {}, 차대번호: {}",
+ generatedId, request.getDmndVhrno(), request.getDmndVin());
+
+ return generatedId;
+ }
+
+ /**
+ * API 응답 결과를 업데이트합니다.
+ *
+ * 기존 레코드에 응답 데이터를 업데이트합니다.
+ * null이 아닌 필드만 업데이트되며, 트랜잭션 내에서 실행됩니다.
+ *
+ * 사용 예시:
+ *
+ * {@code
+ * CarBassMatterInqire response = CarBassMatterInqire.builder()
+ * .carBassMatterInqire("CBMI000000000001")
+ * .cntcResultCode("00")
+ * .cntcResultDtls("성공")
+ * .vhclno("12가3456")
+ * .vin("KMHXX00XXXX000000")
+ * .cnm("소나타")
+ * // ... 기타 응답 필드
+ * .build();
+ *
+ * service.updateResponse(response);
+ * }
+ *
+ *
+ * @param response 응답 정보 (carBassMatterInqire 필드 필수)
+ * @throws RuntimeException 업데이트 실패 시 (레코드가 없는 경우 포함)
+ */
+ @Transactional
+ public void updateResponse(CarBassMatterInqireVO response) {
+ if (response.getCarBassMatterInqire() == null) {
+ throw new IllegalArgumentException("자동차 기본 사항 조회 ID는 필수입니다.");
+ }
+
+ int result = carBassMatterInqireMapper.updateCarBassMatterInqire(response);
+ if (result != 1) {
+ throw new RuntimeException("자동차 기본 사항 조회 정보 업데이트 실패 - ID: " + response.getCarBassMatterInqire());
+ }
+
+ log.info("자동차 기본 사항 조회 정보 업데이트 완료 - ID: {}, 결과코드: {}, 차량번호: {}",
+ response.getCarBassMatterInqire(), response.getCntcResultCode(), response.getVhclno());
+ }
+
+ /**
+ * ID로 조회 정보를 조회합니다.
+ *
+ * @param carBassMatterInqire 자동차 기본 사항 조회 ID
+ * @return 조회된 정보 (없으면 null)
+ */
+ @Transactional(readOnly = true)
+ public CarBassMatterInqireVO getById(String carBassMatterInqire) {
+ return carBassMatterInqireMapper.selectCarBassMatterInqireById(carBassMatterInqire);
+ }
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index d496d2f..69b9ba3 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -1,6 +1,44 @@
server:
port: 8080
+spring:
+ # DataSource 설정 - MariaDB
+ datasource:
+ driver-class-name: org.mariadb.jdbc.Driver
+ url: jdbc:mariadb://211.119.124.117:53306/ibmsdb?characterEncoding=UTF-8&allowMultiQueries=true
+ username: root
+ password: xit5811807
+ hikari:
+ # 커넥션 풀 크기 설정 (4코어 32GB 서버 기준)
+ # 동시에 사용할 수 있는 최대 커넥션 수
+ # 권장값: (코어수 × 2) + (동시사용자 × 0.1) = (4 × 2) + (300 × 0.1) = 38 → 40
+ maximum-pool-size: 40
+ # 풀에서 유지할 최소 유휴 커넥션 수
+ # 권장값: maximum-pool-size의 25% (40 × 0.25 = 10)
+ minimum-idle: 10
+ # 커넥션을 얻기 위한 최대 대기 시간 (밀리초)
+ # 권장값: 30초 - 네트워크 지연이나 데이터베이스 부하 시 적절한 대기 시간
+ connection-timeout: 30000
+ # 커넥션 유효성 검사 타임아웃 (밀리초)
+ validation-timeout: 60000
+ # 커넥션의 최대 생명 시간 (밀리초)
+ # 권장값: 30분 - 데이터베이스 연결이 너무 오래 유지되지 않도록 제한
+ max-lifetime: 1800000
+ # 유휴 커넥션을 제거하기 위한 최소 대기 시간 (밀리초)
+ # 권장값: 10분 - 메모리 절약과 커넥션 재사용의 균형점
+ idle-timeout: 600000
+ # auto-commit을 false로 설정하여 명시적 트랜잭션 관리
+ auto-commit: false
+
+# MyBatis 설정
+mybatis:
+ # MyBatis 전역 설정 파일 위치
+ config-location: classpath:mybatis/mybatis-config.xml
+ # Mapper XML 파일 위치 (DbType 변수 사용)
+ mapper-locations: classpath:mybatis/mapper/**/*_${Globals.DbType}.xml
+ # 타입 별칭 패키지 (하위 패키지 자동 스캔)
+ type-aliases-package: com.vmis.interfaceapp.model
+
# 로그 설정 - 개발(DEV) 환경
logging:
config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-prd.yml b/src/main/resources/application-prd.yml
index e5983b5..9ac423d 100644
--- a/src/main/resources/application-prd.yml
+++ b/src/main/resources/application-prd.yml
@@ -1,6 +1,44 @@
server:
port: 8080
+spring:
+ # DataSource 설정 - MariaDB
+ datasource:
+ driver-class-name: org.mariadb.jdbc.Driver
+ url: jdbc:mariadb://211.119.124.117:53306/ibmsdb?characterEncoding=UTF-8&allowMultiQueries=true
+ username: root
+ password: xit5811807
+ hikari:
+ # 커넥션 풀 크기 설정 (4코어 32GB 서버 기준)
+ # 동시에 사용할 수 있는 최대 커넥션 수
+ # 권장값: (코어수 × 2) + (동시사용자 × 0.1) = (4 × 2) + (300 × 0.1) = 38 → 40
+ maximum-pool-size: 40
+ # 풀에서 유지할 최소 유휴 커넥션 수
+ # 권장값: maximum-pool-size의 25% (40 × 0.25 = 10)
+ minimum-idle: 10
+ # 커넥션을 얻기 위한 최대 대기 시간 (밀리초)
+ # 권장값: 30초 - 네트워크 지연이나 데이터베이스 부하 시 적절한 대기 시간
+ connection-timeout: 30000
+ # 커넥션 유효성 검사 타임아웃 (밀리초)
+ validation-timeout: 60000
+ # 커넥션의 최대 생명 시간 (밀리초)
+ # 권장값: 30분 - 데이터베이스 연결이 너무 오래 유지되지 않도록 제한
+ max-lifetime: 1800000
+ # 유휴 커넥션을 제거하기 위한 최소 대기 시간 (밀리초)
+ # 권장값: 10분 - 메모리 절약과 커넥션 재사용의 균형점
+ idle-timeout: 600000
+ # auto-commit을 false로 설정하여 명시적 트랜잭션 관리
+ auto-commit: false
+
+# MyBatis 설정
+mybatis:
+ # MyBatis 전역 설정 파일 위치
+ config-location: classpath:mybatis/mybatis-config.xml
+ # Mapper XML 파일 위치 (DbType 변수 사용)
+ mapper-locations: classpath:mybatis/mapper/**/*_${Globals.DbType}.xml
+ # 타입 별칭 패키지 (하위 패키지 자동 스캔)
+ type-aliases-package: com.vmis.interfaceapp.model
+
# 로그 설정 - 운영(PRD) 환경
logging:
config: classpath:logback-spring.xml
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 0718988..97c8ccb 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -5,5 +5,9 @@ spring:
pathmatch:
matching-strategy: ant_path_matcher
+# 전역 설정
+Globals:
+ DbType: maria
+
server:
port: 8080
\ No newline at end of file
diff --git a/src/main/resources/mybatis/mapper/CarBassMatterInqireMapper_maria.xml b/src/main/resources/mybatis/mapper/CarBassMatterInqireMapper_maria.xml
new file mode 100644
index 0000000..cc6dd0b
--- /dev/null
+++ b/src/main/resources/mybatis/mapper/CarBassMatterInqireMapper_maria.xml
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+ INSERT INTO tb_car_bass_matter_inqire (
+ CAR_BASS_MATTER_INQIRE,
+ INFO_SYS_ID,
+ INFO_SYS_IP,
+ SIGUNGU_CODE,
+ CNTC_INFO_CODE,
+ CHARGER_ID,
+ CHARGER_IP,
+ CHARGER_NM,
+ DMND_LEVY_STDDE,
+ DMND_INQIRE_SE_CODE,
+ DMND_VHRNO,
+ DMND_VIN,
+ REG_DT,
+ RGTR
+ ) VALUES (
+ #{carBassMatterInqire},
+ #{infoSysId},
+ #{infoSysIp},
+ #{sigunguCode},
+ #{cntcInfoCode},
+ #{chargerId},
+ #{chargerIp},
+ #{chargerNm},
+ #{dmndLevyStdde},
+ #{dmndInqireSeCode},
+ #{dmndVhrno},
+ #{dmndVin},
+ NOW(),
+ #{rgtr}
+ )
+
+
+
+
+ UPDATE tb_car_bass_matter_inqire
+
+ CNTC_RESULT_CODE = #{cntcResultCode},
+ CNTC_RESULT_DTLS = #{cntcResultDtls},
+ PRYE = #{prye},
+ REGIST_DE = #{registDe},
+ ERSR_REGIST_SE_CODE = #{ersrRegistSeCode},
+ ERSR_REGIST_SE_NM = #{ersrRegistSeNm},
+ ERSR_REGIST_DE = #{ersrRegistDe},
+ REGIST_DETAIL_CODE = #{registDetailCode},
+ DSPLVL = #{dsplvl},
+ USE_STRNGHLD_LEGALDONG_CODE = #{useStrnghldLegaldongCode},
+ USE_STRNGHLD_ADSTRD_CODE = #{useStrnghldAdstrdCode},
+ USE_STRNGHLD_MNTN = #{useStrnghldMntn},
+ USE_STRNGHLD_LNBR = #{useStrnghldLnbr},
+ USE_STRNGHLD_HO = #{useStrnghldHo},
+ USE_STRNGHLD_ADRES_NM = #{useStrnghldAdresNm},
+ USE_STRNGHLD_ROAD_NM_CODE = #{useStrnghldRoadNmCode},
+ USGSRHLD_UNDGRND_BULD_SE_CODE = #{usgsrhldUndgrndBuldSeCode},
+ USE_STRNGHLD_BULD_MAIN_NO = #{useStrnghldBuldMainNo},
+ USE_STRNGHLD_BULD_SUB_NO = #{useStrnghldBuldSubNo},
+ USGSRHLD_ADRES_FULL = #{usgsrhldAdresFull},
+ MBER_SE_CODE = #{mberSeCode},
+ MBER_SE_NO = #{mberSeNo},
+ TELNO = #{telno},
+ OWNER_LEGALDONG_CODE = #{ownerLegaldongCode},
+ OWNER_ADSTRD_CODE = #{ownerAdstrdCode},
+ OWNER_MNTN = #{ownerMntn},
+ OWNER_LNBR = #{ownerLnbr},
+ OWNER_HO = #{ownerHo},
+ OWNER_ADRES_NM = #{ownerAdresNm},
+ OWNER_ROAD_NM_CODE = #{ownerRoadNmCode},
+ OWNER_UNDGRND_BULD_SE_CODE = #{ownerUndgrndBuldSeCode},
+ OWNER_BULD_MAIN_NO = #{ownerBuldMainNo},
+ OWNER_BULD_SUB_NO = #{ownerBuldSubNo},
+ OWNR_WHOLADDR = #{ownrWholaddr},
+ AFTR_VHRNO = #{aftrVhrno},
+ USE_FUEL_CODE = #{useFuelCode},
+ PRPOS_SE_CODE = #{prposSeCode},
+ MTRS_FOM_NM = #{mtrsFomNm},
+ FRNT_VHRNO = #{frntVhrno},
+ VHCLNO = #{vhclno},
+ VIN = #{vin},
+ CNM = #{cnm},
+ VHCLE_TOT_WT = #{vhcleTotWt},
+ CAAG_ENDDE = #{caagEndde},
+ CHANGE_DE = #{changeDe},
+ VHCTY_ASORT_CODE = #{vhctyAsortCode},
+ VHCTY_TY_CODE = #{vhctyTyCode},
+ VHCTY_SE_CODE = #{vhctySeCode},
+ MXMM_LDG = #{mxmmLdg},
+ VHCTY_ASORT_NM = #{vhctyAsortNm},
+ VHCTY_TY_NM = #{vhctyTyNm},
+ VHCTY_SE_NM = #{vhctySeNm},
+ FRST_REGIST_DE = #{frstRegistDe},
+ FOM_NM = #{fomNm},
+ ACQS_DE = #{acqsDe},
+ ACQS_END_DE = #{acqsEndDe},
+ YBL_MD = #{yblMd},
+ TRANSR_REGIST_DE = #{transrRegistDe},
+ SPCF_REGIST_STTUS_CODE = #{spcfRegistSttusCode},
+ COLOR_NM = #{colorNm},
+ MRTG_CO = #{mrtgCo},
+ SEIZR_CO = #{seizrCo},
+ STMD_CO = #{stmdCo},
+ NMPL_CSDY_AT = #{nmplCsdyAt},
+ NMPL_CSDY_REMNR_DE = #{nmplCsdyRemnrDe},
+ ORIGIN_SE_CODE = #{originSeCode},
+ NMPL_STNDRD_CODE = #{nmplStndrdCode},
+ ACQS_AMOUNT = #{acqsAmount},
+ INSPT_VALID_PD_BGNDE = #{insptValidPdBgnde},
+ INSPT_VALID_PD_ENDDE = #{insptValidPdEndde},
+ USE_STRNGHLD_GRC_CODE = #{useStrnghldGrcCode},
+ TKCAR_PSCAP_CO = #{tkcarPscapCo},
+ SPMNNO = #{spmnno},
+ TRVL_DSTNC = #{trvlDstnc},
+ FRST_REGIST_RQRCNO = #{frstRegistRqrcno},
+ VLNT_ERSR_PRVNTC_NTICE_DE = #{vlntErsrPrvntcNticeDe},
+ REGIST_INSTT_NM = #{registInsttNm},
+ PROCESS_IMPRTY_RESN_CODE = #{processImprtyResnCode},
+ PROCESS_IMPRTY_RESN_DTLS = #{processImprtyResnDtls},
+ CBD_LT = #{cbdLt},
+ CBD_BT = #{cbdBt},
+ CBD_HG = #{cbdHg},
+ FRST_MXMM_LDG = #{frstMxmmLdg},
+ FUEL_CNSMP_RT = #{fuelCnsmpRt},
+ ELCTY_CMPND_FUEL_CNSMP_RT = #{elctyCmpndFuelCnsmpRt},
+ MBER_NM = #{mberNm},
+
+ WHERE CAR_BASS_MATTER_INQIRE = #{carBassMatterInqire}
+
+
+
+
+
+
diff --git a/src/main/resources/mybatis/mapper/sample_maria.xml b/src/main/resources/mybatis/mapper/sample_maria.xml
new file mode 100644
index 0000000..b1a4c7f
--- /dev/null
+++ b/src/main/resources/mybatis/mapper/sample_maria.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/mybatis/mybatis-config.xml b/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..2f288d1
--- /dev/null
+++ b/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+