차량기본정보 API, DB 저장 로직 추가

추가적으로 소스 리팩토링 예정
main
박성영 1 month ago
parent 6f5b2c7ee3
commit 2a14d6b212

@ -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'

@ -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'));

@ -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 '자동차 기본 사항 조회';

@ -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;
/**
*
*
* <p>API DB .</p>
*/
private final com.vmis.interfaceapp.service.CarBassMatterInqireService carBassMatterInqireService;
/**
*
*
@ -156,134 +166,6 @@ public class GovernmentApiClient {
*/
LEDGER }
/**
*
*
* <p>Spring .
*
* @param restTemplate HTTP RestTemplate
* @param props VMIS
* @param gpkiService GPKI /
* @param objectMapper JSON / ObjectMapper
* @Component Spring Bean .</p> <h4> :</h4> <ul> <li> ( )</li> <li> ( final )</li> <li> (Mock )</li> <li> ( )</li> </ul>
*/
public GovernmentApiClient(RestTemplate restTemplate, VmisProperties props, GpkiService gpkiService, ObjectMapper objectMapper) {
this.restTemplate = restTemplate;
this.props = props;
this.gpkiService = gpkiService;
this.objectMapper = objectMapper;
}
/**
* API ( )
*
* <p> JSON API (Low-level) .
* {@link #callModel} .</p>
*
* <h3> :</h3>
* <ol>
* <li><b> :</b> API </li>
* <li><b>URL :</b> , , URL </li>
* <li><b> ID :</b> ID (TxIdUtil )</li>
* <li><b> :</b> (API , , GPKI ) </li>
* <li><b> :</b> GPKI </li>
* <li><b>HTTP :</b> RestTemplate POST </li>
* <li><b> :</b> GPKI </li>
* <li><b> :</b> ResponseEntity </li>
* </ol>
*
* <h3> :</h3>
* <ul>
* <li><b>GPKI :</b> RuntimeException </li>
* <li><b>HTTP (4xx, 5xx):</b> </li>
* <li><b>GPKI :</b> RuntimeException </li>
* </ul>
*
* <h3>:</h3>
* <ul>
* <li> : URL, ID, GPKI , </li>
* <li> : HTTP , </li>
* </ul>
*
* @param type (BASIC LEDGER)
* @param jsonBody JSON ( )
* @return ResponseEntity&lt;String&gt; API ( JSON )
* @throws RuntimeException GPKI /
*/
public ResponseEntity<String> call(ServiceType type, String jsonBody) {
// 1. 서비스 타입에 따른 설정 로드
// props.getGov()는 정부 API 관련 모든 설정을 포함하는 객체를 반환
VmisProperties.GovProps gov = props.getGov();
// 삼항 연산자를 사용하여 BASIC 또는 LEDGER 서비스 설정 선택
VmisProperties.GovProps.Service svc = (type == ServiceType.BASIC)
? gov.getServices().getBasic()
: gov.getServices().getLedger();
// 2. 완전한 URL 구성 (예: https://api.gov.kr:8080/vmis/basic)
String url = gov.buildServiceUrl(svc.getPath());
// 3. 트랜잭션 ID 생성 (요청 추적 및 디버깅 용도)
// 일반적으로 타임스탬프 + UUID 조합으로 생성됨
String txId = TxIdUtil.generate();
// 4. HTTP 헤더 구성
// API 키, 시스템 정보, GPKI 설정 등 필수 헤더 포함
HttpHeaders headers = buildHeaders(svc, txId);
// 5. GPKI 암호화 처리
String bodyToSend = jsonBody;
if (gpkiService.isEnabled()) {
try {
// 평문 JSON을 암호화된 문자열로 변환
// 암호화 결과는 Base64 인코딩된 문자열
bodyToSend = gpkiService.encrypt(jsonBody);
} catch (Exception e) {
// 암호화 실패는 치명적 오류이므로 즉시 예외 발생
throw new RuntimeException("GPKI 암호화 실패", e);
}
}
// 6. HTTP 엔티티 생성 (헤더 + 바디)
HttpEntity<String> request = new HttpEntity<>(bodyToSend, headers);
// 7. 요청 로그 기록
// 디버깅을 위해 URL, 트랜잭션 ID, GPKI 활성화 여부, 바디 길이 로깅
log.info("[GOV-REQ] url={}, tx_id={}, gpki={}, length={}", url, txId, gpkiService.isEnabled(), bodyToSend != null ? bodyToSend.length() : 0);
try {
// 8. 실제 HTTP POST 요청 전송
// RestTemplate.exchange()는 HTTP 메서드, 헤더, 바디를 모두 지정 가능
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
String respBody = response.getBody();
// 9. 성공 응답인 경우 GPKI 복호화 처리
if (gpkiService.isEnabled() && response.getStatusCode().is2xxSuccessful()) {
try {
// 암호화된 응답을 평문 JSON으로 복호화
String decrypted = gpkiService.decrypt(respBody);
// 복호화된 바디로 새로운 ResponseEntity 생성
// 원본 응답의 상태 코드와 헤더는 그대로 유지
return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(decrypted);
} catch (Exception e) {
// 복호화 실패는 치명적 오류이므로 즉시 예외 발생
throw new RuntimeException("GPKI 복호화 실패", e);
}
}
// GPKI가 비활성화되어 있거나 에러 응답인 경우 원본 그대로 반환
return response;
} catch (HttpStatusCodeException ex) {
// 10. HTTP 에러 처리 (4xx, 5xx 상태 코드)
// 경고 로그 기록 (에러는 정상적인 비즈니스 흐름일 수 있으므로 WARN 레벨)
log.warn("[GOV-ERR] status={}, body={}", ex.getStatusCode(), ex.getResponseBodyAsString());
// 에러 응답을 ResponseEntity로 변환하여 반환
// 호출자가 상태 코드와 에러 메시지를 확인할 수 있도록 함
// 헤더가 null인 경우를 대비하여 빈 HttpHeaders 사용
return ResponseEntity.status(ex.getStatusCode()).headers(ex.getResponseHeaders() != null ? ex.getResponseHeaders() : new HttpHeaders()).body(ex.getResponseBodyAsString());
}
}
/**
* HTTP
*
@ -398,10 +280,6 @@ public class GovernmentApiClient {
// CVMIS(Car Vehicle Management Information System) 전용 API 키
headers.add("cvmis_apikey", svc.getCvmisApikey());
// 9. 정보시스템 ID
// 호출하는 시스템을 식별하는 필수 값
headers.add("INFO_SYS_ID", props.getSystem().getInfoSysId());
// 구성 완료된 헤더 반환
return headers;
}
@ -414,11 +292,20 @@ public class GovernmentApiClient {
*
* <h3>:</h3>
* <ul>
* <li> </li>
* <li> </li>
* <li>/ Envelope </li>
* <li>Jackson TypeReference </li>
* <li>API DB </li>
* </ul>
*
* <h3> :</h3>
* <ol>
* <li> DB INSERT ( )</li>
* <li> API </li>
* <li> DB UPDATE</li>
* <li> DB UPDATE</li>
* </ol>
*
* <h3> :</h3>
* <pre>
* BasicRequest request = new BasicRequest();
@ -435,9 +322,34 @@ public class GovernmentApiClient {
* @return ResponseEntity&lt;Envelope&lt;BasicResponse&gt;&gt;
*/
public ResponseEntity<Envelope<BasicResponse>> callBasic(Envelope<BasicRequest> envelope) {
// TypeReference를 사용하여 제네릭 타입 정보 전달
// 익명 클래스를 생성하여 타입 소거(Type Erasure) 문제 해결
return callModel(ServiceType.BASIC, envelope, new TypeReference<Envelope<BasicResponse>>(){});
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<Envelope<BasicResponse>> response = callModel(ServiceType.BASIC, envelope, new TypeReference<Envelope<BasicResponse>>(){});
// 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<com.vmis.interfaceapp.model.basic.BasicResponse> 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);
}
}
}

@ -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;
/**
*
*
* <p> .
* Spring Boot ,
* TransactionManager .</p>
*
* <ul>
* <li>DataSource: application.yml </li>
* <li>SqlSessionFactory: MyBatis Spring Boot Starter </li>
* <li>TransactionManager: </li>
* <li>MapperScan: com.vmis.interfaceapp.mapper Mapper </li>
* </ul>
*/
@Configuration
@EnableTransactionManagement
@MapperScan("com.vmis.interfaceapp.mapper")
public class DatabaseConfig {
/**
* .
*
* <p>DataSourceTransactionManager JDBC .
* @Transactional .</p>
*
* <p> (Propagation), (Isolation),
* @Transactional .</p>
*
* <p>:</p>
* <pre>
* {@code
* @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
* public void saveData() {
* // 트랜잭션 처리가 필요한 로직
* }
* }
* </pre>
*
* @param dataSource Spring Boot DataSource
* @return PlatformTransactionManager
*/
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

@ -0,0 +1,39 @@
package com.vmis.interfaceapp.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
*
*
* <p> .
* Spring @Value application.yml .</p>
*/
@Component
public class Globals {
/**
* (: mariadb, oracle, mysql )
*
* <p>MyBatis Mapper XML .
* mapper-locations: classpath:mybatis/mapper/**\/*_${Globals.DbType}.xml</p>
*
* <p>:
* <ul>
* <li>DbType = "mariadb" user_mariadb.xml </li>
* <li>DbType = "oracle" user_oracle.xml </li>
* </ul>
* </p>
*/
public static String DbType;
/**
* application.yml Globals.DbType .
*
* @param dbType (: mariadb)
*/
@Value("${Globals.DbType:mariadb}")
public void setDbType(String dbType) {
Globals.DbType = dbType;
}
}

@ -0,0 +1,54 @@
package com.vmis.interfaceapp.mapper;
import com.vmis.interfaceapp.model.basic.CarBassMatterInqireVO;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper
*
* <p>API Mapper .</p>
* <ul>
* <li> : insertCarBassMatterInqire() </li>
* <li> : updateCarBassMatterInqire() </li>
* </ul>
*/
@Mapper
public interface CarBassMatterInqireMapper {
/**
* 퀀 ID .
*
* <p>: CBMI000000000001</p>
*
* @return ID
*/
String selectNextCarBassMatterInqireId();
/**
* API .
*
* <p> , null .</p>
*
* @param carBassMatterInqireVO
* @return
*/
int insertCarBassMatterInqire(CarBassMatterInqireVO carBassMatterInqireVO);
/**
* API .
*
* <p> .</p>
*
* @param carBassMatterInqireVO (carBassMatterInqire )
* @return
*/
int updateCarBassMatterInqire(CarBassMatterInqireVO carBassMatterInqireVO);
/**
* ID .
*
* @param carBassMatterInqire ID
* @return
*/
CarBassMatterInqireVO selectCarBassMatterInqireById(String carBassMatterInqire);
}

@ -0,0 +1,26 @@
package com.vmis.interfaceapp.mapper;
import org.apache.ibatis.annotations.Mapper;
/**
* MyBatis Mapper
*
* <p> MyBatis .
* Mapper .</p>
*
* <p>@Mapper Spring .
* XML namespace .</p>
*/
@Mapper
public interface SampleMapper {
/**
*
*
* <p>
* .</p>
*
* @return
*/
String selectCurrentTime();
}

@ -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;
/**
*
*
* <p>API .
* INSERT, UPDATE .</p>
*/
@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;
}

@ -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;
/**
*
*
* <p>API .</p>
* <ul>
* <li> : createInitialRequest() - 퀀 ID INSERT</li>
* <li> : updateResponse() - UPDATE</li>
* </ul>
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class CarBassMatterInqireService {
private final CarBassMatterInqireMapper carBassMatterInqireMapper;
/**
* API .
*
* <p>퀀 ID .
* , .</p>
*
* <p> :</p>
* <pre>
* {@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);
* }
* </pre>
*
* @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 .
*
* <p> .
* null , .</p>
*
* <p> :</p>
* <pre>
* {@code
* CarBassMatterInqire response = CarBassMatterInqire.builder()
* .carBassMatterInqire("CBMI000000000001")
* .cntcResultCode("00")
* .cntcResultDtls("성공")
* .vhclno("12가3456")
* .vin("KMHXX00XXXX000000")
* .cnm("소나타")
* // ... 기타 응답 필드
* .build();
*
* service.updateResponse(response);
* }
* </pre>
*
* @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);
}
}

@ -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

@ -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

@ -5,5 +5,9 @@ spring:
pathmatch:
matching-strategy: ant_path_matcher
# 전역 설정
Globals:
DbType: maria
server:
port: 8080

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vmis.interfaceapp.mapper.CarBassMatterInqireMapper">
<!-- 시퀀스로 새로운 ID 생성 -->
<select id="selectNextCarBassMatterInqireId" resultType="String">
SELECT CONCAT('CBMI', LPAD(NEXTVAL(seq_car_bass_matter_inqire), 16, '0')) AS id
</select>
<!-- 최초 요청 정보 INSERT -->
<insert id="insertCarBassMatterInqire" parameterType="CarBassMatterInqireVO">
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}
)
</insert>
<!-- 응답 결과 UPDATE -->
<update id="updateCarBassMatterInqire" parameterType="CarBassMatterInqireVO">
UPDATE tb_car_bass_matter_inqire
<set>
<if test="cntcResultCode != null">CNTC_RESULT_CODE = #{cntcResultCode},</if>
<if test="cntcResultDtls != null">CNTC_RESULT_DTLS = #{cntcResultDtls},</if>
<if test="prye != null">PRYE = #{prye},</if>
<if test="registDe != null">REGIST_DE = #{registDe},</if>
<if test="ersrRegistSeCode != null">ERSR_REGIST_SE_CODE = #{ersrRegistSeCode},</if>
<if test="ersrRegistSeNm != null">ERSR_REGIST_SE_NM = #{ersrRegistSeNm},</if>
<if test="ersrRegistDe != null">ERSR_REGIST_DE = #{ersrRegistDe},</if>
<if test="registDetailCode != null">REGIST_DETAIL_CODE = #{registDetailCode},</if>
<if test="dsplvl != null">DSPLVL = #{dsplvl},</if>
<if test="useStrnghldLegaldongCode != null">USE_STRNGHLD_LEGALDONG_CODE = #{useStrnghldLegaldongCode},</if>
<if test="useStrnghldAdstrdCode != null">USE_STRNGHLD_ADSTRD_CODE = #{useStrnghldAdstrdCode},</if>
<if test="useStrnghldMntn != null">USE_STRNGHLD_MNTN = #{useStrnghldMntn},</if>
<if test="useStrnghldLnbr != null">USE_STRNGHLD_LNBR = #{useStrnghldLnbr},</if>
<if test="useStrnghldHo != null">USE_STRNGHLD_HO = #{useStrnghldHo},</if>
<if test="useStrnghldAdresNm != null">USE_STRNGHLD_ADRES_NM = #{useStrnghldAdresNm},</if>
<if test="useStrnghldRoadNmCode != null">USE_STRNGHLD_ROAD_NM_CODE = #{useStrnghldRoadNmCode},</if>
<if test="usgsrhldUndgrndBuldSeCode != null">USGSRHLD_UNDGRND_BULD_SE_CODE = #{usgsrhldUndgrndBuldSeCode},</if>
<if test="useStrnghldBuldMainNo != null">USE_STRNGHLD_BULD_MAIN_NO = #{useStrnghldBuldMainNo},</if>
<if test="useStrnghldBuldSubNo != null">USE_STRNGHLD_BULD_SUB_NO = #{useStrnghldBuldSubNo},</if>
<if test="usgsrhldAdresFull != null">USGSRHLD_ADRES_FULL = #{usgsrhldAdresFull},</if>
<if test="mberSeCode != null">MBER_SE_CODE = #{mberSeCode},</if>
<if test="mberSeNo != null">MBER_SE_NO = #{mberSeNo},</if>
<if test="telno != null">TELNO = #{telno},</if>
<if test="ownerLegaldongCode != null">OWNER_LEGALDONG_CODE = #{ownerLegaldongCode},</if>
<if test="ownerAdstrdCode != null">OWNER_ADSTRD_CODE = #{ownerAdstrdCode},</if>
<if test="ownerMntn != null">OWNER_MNTN = #{ownerMntn},</if>
<if test="ownerLnbr != null">OWNER_LNBR = #{ownerLnbr},</if>
<if test="ownerHo != null">OWNER_HO = #{ownerHo},</if>
<if test="ownerAdresNm != null">OWNER_ADRES_NM = #{ownerAdresNm},</if>
<if test="ownerRoadNmCode != null">OWNER_ROAD_NM_CODE = #{ownerRoadNmCode},</if>
<if test="ownerUndgrndBuldSeCode != null">OWNER_UNDGRND_BULD_SE_CODE = #{ownerUndgrndBuldSeCode},</if>
<if test="ownerBuldMainNo != null">OWNER_BULD_MAIN_NO = #{ownerBuldMainNo},</if>
<if test="ownerBuldSubNo != null">OWNER_BULD_SUB_NO = #{ownerBuldSubNo},</if>
<if test="ownrWholaddr != null">OWNR_WHOLADDR = #{ownrWholaddr},</if>
<if test="aftrVhrno != null">AFTR_VHRNO = #{aftrVhrno},</if>
<if test="useFuelCode != null">USE_FUEL_CODE = #{useFuelCode},</if>
<if test="prposSeCode != null">PRPOS_SE_CODE = #{prposSeCode},</if>
<if test="mtrsFomNm != null">MTRS_FOM_NM = #{mtrsFomNm},</if>
<if test="frntVhrno != null">FRNT_VHRNO = #{frntVhrno},</if>
<if test="vhclno != null">VHCLNO = #{vhclno},</if>
<if test="vin != null">VIN = #{vin},</if>
<if test="cnm != null">CNM = #{cnm},</if>
<if test="vhcleTotWt != null">VHCLE_TOT_WT = #{vhcleTotWt},</if>
<if test="caagEndde != null">CAAG_ENDDE = #{caagEndde},</if>
<if test="changeDe != null">CHANGE_DE = #{changeDe},</if>
<if test="vhctyAsortCode != null">VHCTY_ASORT_CODE = #{vhctyAsortCode},</if>
<if test="vhctyTyCode != null">VHCTY_TY_CODE = #{vhctyTyCode},</if>
<if test="vhctySeCode != null">VHCTY_SE_CODE = #{vhctySeCode},</if>
<if test="mxmmLdg != null">MXMM_LDG = #{mxmmLdg},</if>
<if test="vhctyAsortNm != null">VHCTY_ASORT_NM = #{vhctyAsortNm},</if>
<if test="vhctyTyNm != null">VHCTY_TY_NM = #{vhctyTyNm},</if>
<if test="vhctySeNm != null">VHCTY_SE_NM = #{vhctySeNm},</if>
<if test="frstRegistDe != null">FRST_REGIST_DE = #{frstRegistDe},</if>
<if test="fomNm != null">FOM_NM = #{fomNm},</if>
<if test="acqsDe != null">ACQS_DE = #{acqsDe},</if>
<if test="acqsEndDe != null">ACQS_END_DE = #{acqsEndDe},</if>
<if test="yblMd != null">YBL_MD = #{yblMd},</if>
<if test="transrRegistDe != null">TRANSR_REGIST_DE = #{transrRegistDe},</if>
<if test="spcfRegistSttusCode != null">SPCF_REGIST_STTUS_CODE = #{spcfRegistSttusCode},</if>
<if test="colorNm != null">COLOR_NM = #{colorNm},</if>
<if test="mrtgCo != null">MRTG_CO = #{mrtgCo},</if>
<if test="seizrCo != null">SEIZR_CO = #{seizrCo},</if>
<if test="stmdCo != null">STMD_CO = #{stmdCo},</if>
<if test="nmplCsdyAt != null">NMPL_CSDY_AT = #{nmplCsdyAt},</if>
<if test="nmplCsdyRemnrDe != null">NMPL_CSDY_REMNR_DE = #{nmplCsdyRemnrDe},</if>
<if test="originSeCode != null">ORIGIN_SE_CODE = #{originSeCode},</if>
<if test="nmplStndrdCode != null">NMPL_STNDRD_CODE = #{nmplStndrdCode},</if>
<if test="acqsAmount != null">ACQS_AMOUNT = #{acqsAmount},</if>
<if test="insptValidPdBgnde != null">INSPT_VALID_PD_BGNDE = #{insptValidPdBgnde},</if>
<if test="insptValidPdEndde != null">INSPT_VALID_PD_ENDDE = #{insptValidPdEndde},</if>
<if test="useStrnghldGrcCode != null">USE_STRNGHLD_GRC_CODE = #{useStrnghldGrcCode},</if>
<if test="tkcarPscapCo != null">TKCAR_PSCAP_CO = #{tkcarPscapCo},</if>
<if test="spmnno != null">SPMNNO = #{spmnno},</if>
<if test="trvlDstnc != null">TRVL_DSTNC = #{trvlDstnc},</if>
<if test="frstRegistRqrcno != null">FRST_REGIST_RQRCNO = #{frstRegistRqrcno},</if>
<if test="vlntErsrPrvntcNticeDe != null">VLNT_ERSR_PRVNTC_NTICE_DE = #{vlntErsrPrvntcNticeDe},</if>
<if test="registInsttNm != null">REGIST_INSTT_NM = #{registInsttNm},</if>
<if test="processImprtyResnCode != null">PROCESS_IMPRTY_RESN_CODE = #{processImprtyResnCode},</if>
<if test="processImprtyResnDtls != null">PROCESS_IMPRTY_RESN_DTLS = #{processImprtyResnDtls},</if>
<if test="cbdLt != null">CBD_LT = #{cbdLt},</if>
<if test="cbdBt != null">CBD_BT = #{cbdBt},</if>
<if test="cbdHg != null">CBD_HG = #{cbdHg},</if>
<if test="frstMxmmLdg != null">FRST_MXMM_LDG = #{frstMxmmLdg},</if>
<if test="fuelCnsmpRt != null">FUEL_CNSMP_RT = #{fuelCnsmpRt},</if>
<if test="elctyCmpndFuelCnsmpRt != null">ELCTY_CMPND_FUEL_CNSMP_RT = #{elctyCmpndFuelCnsmpRt},</if>
<if test="mberNm != null">MBER_NM = #{mberNm},</if>
</set>
WHERE CAR_BASS_MATTER_INQIRE = #{carBassMatterInqire}
</update>
<!-- ID로 조회 -->
<select id="selectCarBassMatterInqireById" parameterType="String" resultType="CarBassMatterInqireVO">
SELECT *
FROM tb_car_bass_matter_inqire
WHERE CAR_BASS_MATTER_INQIRE = #{carBassMatterInqire}
</select>
</mapper>

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
샘플 MyBatis Mapper XML 파일
실제 사용 시에는 테이블명과 컬럼명을 프로젝트에 맞게 수정하세요.
이 파일은 설정 테스트 및 예제 용도입니다.
-->
<mapper namespace="com.vmis.interfaceapp.mapper.SampleMapper">
<!-- 샘플 쿼리: 데이터베이스 연결 테스트 -->
<select id="selectCurrentTime" resultType="String">
SELECT NOW() AS current_time
</select>
<!--
추가 쿼리 예제:
<select id="selectById" parameterType="Long" resultType="com.vmis.interfaceapp.model.SampleEntity">
SELECT id, name, created_at
FROM sample_table
WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.vmis.interfaceapp.model.SampleEntity">
INSERT INTO sample_table (name, created_at)
VALUES (#{name}, NOW())
</insert>
<update id="update" parameterType="com.vmis.interfaceapp.model.SampleEntity">
UPDATE sample_table
SET name = #{name}
WHERE id = #{id}
</update>
<delete id="delete" parameterType="Long">
DELETE FROM sample_table
WHERE id = #{id}
</delete>
-->
</mapper>

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 설정 -->
<settings>
<!-- 카멜케이스 자동 매핑 (DB의 snake_case를 Java의 camelCase로 자동 변환) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- JDBC 타입이 null일 때의 처리 (NULL 값 허용) -->
<setting name="jdbcTypeForNull" value="NULL"/>
<!-- 쿼리 실행 시 로그 출력 레벨 설정 -->
<setting name="logImpl" value="SLF4J"/>
<!-- 결과가 null일 때도 객체 생성 -->
<setting name="callSettersOnNulls" value="true"/>
<!-- 지연 로딩 설정 (필요시 변경) -->
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 캐시 사용 설정 -->
<setting name="cacheEnabled" value="false"/>
<!-- 자동 생성 키 사용 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 디폴트 Executor 타입 (SIMPLE, REUSE, BATCH) -->
<setting name="defaultExecutorType" value="REUSE"/>
<!-- 타임아웃 설정 (초 단위, null이면 무제한) -->
<setting name="defaultStatementTimeout" value="25"/>
</settings>
<!-- 타입 별칭 설정 (선택사항) -->
<!-- type-aliases-package로 자동 스캔되므로 여기서는 생략 가능 -->
<typeAliases>
<!-- 필요시 추가 -->
</typeAliases>
<!-- 타입 핸들러 설정 (선택사항) -->
<typeHandlers>
<!-- 필요시 추가 -->
</typeHandlers>
</configuration>
Loading…
Cancel
Save