feat : 배치, 익스쿼리 미사용으로 제거
parent
9865e6b31a
commit
e7618fbb2e
@ -1,224 +0,0 @@
|
||||
package go.kr.project.system.execquery.config;
|
||||
|
||||
import go.kr.project.system.execquery.exception.TransactionException;
|
||||
import go.kr.project.system.execquery.model.TransactionInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class IsolatedTransactionManager {
|
||||
|
||||
private final DataSource queryDataSource;
|
||||
private final Map<String, TransactionInfo> transactions = new ConcurrentHashMap<>();
|
||||
|
||||
private long transactionTimeout; // 트랜잭션 타임아웃 (밀리초)
|
||||
|
||||
public IsolatedTransactionManager(@Qualifier("dataSource") DataSource queryDataSource,
|
||||
@Value("${query-executor.transaction.timeout-minutes:5}") int timeoutMinutes) {
|
||||
this.queryDataSource = queryDataSource;
|
||||
// yml에서 분 단위로 설정된 값을 밀리초로 변환
|
||||
this.transactionTimeout = timeoutMinutes * 60 * 1000L; // 분 -> 밀리초 변환
|
||||
log.info("트랜잭션 타임아웃 설정: {}분 ({}ms)", timeoutMinutes, this.transactionTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 새 트랜잭션을 시작하고 트랜잭션 ID를 반환
|
||||
*/
|
||||
public String beginTransaction() throws SQLException {
|
||||
String transactionId = UUID.randomUUID().toString();
|
||||
String sessionId = getCurrentSessionId();
|
||||
|
||||
Connection conn = queryDataSource.getConnection();
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
TransactionInfo info = new TransactionInfo();
|
||||
info.setConnection(conn);
|
||||
info.setLastAccessTime(System.currentTimeMillis());
|
||||
info.setCreationTime(System.currentTimeMillis());
|
||||
info.setSessionId(sessionId);
|
||||
|
||||
transactions.put(transactionId, info);
|
||||
log.debug("트랜잭션 시작: {}, 세션: {}", transactionId, sessionId);
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 ID로 커넥션을 반환
|
||||
*/
|
||||
public Connection getConnection(String transactionId) throws SQLException {
|
||||
if (transactionId == null || transactionId.isEmpty()) {
|
||||
return beginNewConnection();
|
||||
}
|
||||
|
||||
if (!transactions.containsKey(transactionId)) {
|
||||
throw new TransactionException("존재하지 않는 트랜잭션 ID: " + transactionId);
|
||||
}
|
||||
|
||||
TransactionInfo info = transactions.get(transactionId);
|
||||
String currentSessionId = getCurrentSessionId();
|
||||
|
||||
// 세션 ID가 일치하는지 확인
|
||||
if (!currentSessionId.equals(info.getSessionId())) {
|
||||
throw new TransactionException("트랜잭션 접근 권한이 없습니다. 다른 세션에서 생성된 트랜잭션입니다.");
|
||||
}
|
||||
|
||||
info.setLastAccessTime(System.currentTimeMillis());
|
||||
return info.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동 커밋이 활성화된 새 커넥션 반환 (SELECT 전용)
|
||||
*/
|
||||
private Connection beginNewConnection() throws SQLException {
|
||||
Connection conn = queryDataSource.getConnection();
|
||||
conn.setAutoCommit(true);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 커밋
|
||||
*/
|
||||
public void commitTransaction(String transactionId) throws SQLException {
|
||||
if (!transactions.containsKey(transactionId)) {
|
||||
throw new TransactionException("존재하지 않는 트랜잭션 ID: " + transactionId);
|
||||
}
|
||||
|
||||
TransactionInfo info = transactions.get(transactionId);
|
||||
String currentSessionId = getCurrentSessionId();
|
||||
|
||||
if (!currentSessionId.equals(info.getSessionId())) {
|
||||
throw new TransactionException("트랜잭션 접근 권한이 없습니다. 다른 세션에서 생성된 트랜잭션입니다.");
|
||||
}
|
||||
|
||||
try {
|
||||
info.getConnection().commit();
|
||||
log.debug("트랜잭션 커밋: {}", transactionId);
|
||||
closeAndRemove(transactionId);
|
||||
} catch (SQLException e) {
|
||||
log.error("트랜잭션 커밋 중 오류 발생: {}", e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 롤백
|
||||
*/
|
||||
public void rollbackTransaction(String transactionId) throws SQLException {
|
||||
if (!transactions.containsKey(transactionId)) {
|
||||
throw new TransactionException("존재하지 않는 트랜잭션 ID: " + transactionId);
|
||||
}
|
||||
|
||||
TransactionInfo info = transactions.get(transactionId);
|
||||
String currentSessionId = getCurrentSessionId();
|
||||
|
||||
if (!currentSessionId.equals(info.getSessionId())) {
|
||||
throw new TransactionException("트랜잭션 접근 권한이 없습니다. 다른 세션에서 생성된 트랜잭션입니다.");
|
||||
}
|
||||
|
||||
try {
|
||||
info.getConnection().rollback();
|
||||
log.debug("트랜잭션 롤백: {}", transactionId);
|
||||
closeAndRemove(transactionId);
|
||||
} catch (SQLException e) {
|
||||
log.error("트랜잭션 롤백 중 오류 발생: {}", e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 종료 및 제거
|
||||
*/
|
||||
private void closeAndRemove(String transactionId) {
|
||||
TransactionInfo info = transactions.get(transactionId);
|
||||
if (info != null) {
|
||||
try {
|
||||
info.getConnection().close();
|
||||
} catch (SQLException e) {
|
||||
log.error("커넥션 닫기 중 오류 발생: {}", e.getMessage(), e);
|
||||
} finally {
|
||||
transactions.remove(transactionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 세션 ID 반환
|
||||
*/
|
||||
private String getCurrentSessionId() {
|
||||
try {
|
||||
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
HttpServletRequest request = attr.getRequest();
|
||||
HttpSession session = request.getSession(true);
|
||||
return session.getId();
|
||||
} catch (Exception e) {
|
||||
log.warn("세션 ID 가져오기 실패: {}", e.getMessage());
|
||||
return "unknown-session";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 유휴 트랜잭션 정리 (1분마다 실행)
|
||||
*/
|
||||
@Scheduled(fixedRate = 60000)
|
||||
public void cleanupIdleTransactions() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
transactions.entrySet().removeIf(entry -> {
|
||||
TransactionInfo info = entry.getValue();
|
||||
boolean isTimeout = (currentTime - info.getLastAccessTime() > transactionTimeout);
|
||||
|
||||
if (isTimeout) {
|
||||
try {
|
||||
info.getConnection().rollback();
|
||||
info.getConnection().close();
|
||||
log.info("유휴 트랜잭션 정리: {}, 세션: {}, 경과 시간: {}ms",
|
||||
entry.getKey(),
|
||||
info.getSessionId(),
|
||||
currentTime - info.getCreationTime());
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
log.error("유휴 트랜잭션 정리 중 오류 발생: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 세션의 모든 트랜잭션 롤백 및 정리
|
||||
*/
|
||||
public void cleanupSessionTransactions(String sessionId) {
|
||||
if (sessionId == null) return;
|
||||
|
||||
transactions.entrySet().removeIf(entry -> {
|
||||
TransactionInfo info = entry.getValue();
|
||||
if (sessionId.equals(info.getSessionId())) {
|
||||
try {
|
||||
info.getConnection().rollback();
|
||||
info.getConnection().close();
|
||||
log.info("세션 종료로 인한 트랜잭션 정리: {}", entry.getKey());
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
log.error("세션 트랜잭션 정리 중 오류 발생: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
package go.kr.project.system.execquery.controller;
|
||||
|
||||
import egovframework.constant.TilesConstants;
|
||||
import go.kr.project.system.execquery.model.QueryRequest;
|
||||
import go.kr.project.system.execquery.model.QueryResponse;
|
||||
import go.kr.project.system.execquery.service.DbQueryService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
@RequestMapping("/db/exec")
|
||||
public class DbQueryController {
|
||||
|
||||
private final DbQueryService dbQueryService;
|
||||
|
||||
/**
|
||||
* <pre>메소드 설명: 메인 페이지</pre>
|
||||
* @param req
|
||||
* @return String 요청처리 후 응답객체
|
||||
* @author: 최정민
|
||||
* @date: 2021. 9. 27.
|
||||
*/
|
||||
@GetMapping(value = "query.do")
|
||||
public String query(HttpServletRequest req, Model model) {
|
||||
|
||||
return "system/db/exec" + TilesConstants.BASE;
|
||||
}
|
||||
|
||||
@PostMapping("/queryexec.do")
|
||||
public ResponseEntity<QueryResponse> executeQuery(
|
||||
@RequestBody QueryRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
|
||||
try {
|
||||
// Base64 인코딩된 쿼리가 있으면 디코딩
|
||||
if (request.isBase64Encoded() && request.getQuery() != null) {
|
||||
String base64Query = request.getQuery();
|
||||
log.info("Base64 인코딩된 쿼리 수신: {}", base64Query);
|
||||
|
||||
// Base64 디코딩
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(base64Query);
|
||||
String decodedQuery = new String(decodedBytes, StandardCharsets.UTF_8);
|
||||
|
||||
log.info("디코딩된 쿼리: {}", decodedQuery);
|
||||
// 개별 쿼리를 받으므로 세미콜론 제거 로직을 수정
|
||||
// 쿼리 끝의 세미콜론만 제거 (중간에 있는 세미콜론은 유지)
|
||||
String cleanedQuery = decodedQuery.trim();
|
||||
if (cleanedQuery.endsWith(";")) {
|
||||
cleanedQuery = cleanedQuery.substring(0, cleanedQuery.length() - 1).trim();
|
||||
}
|
||||
request.setQuery(cleanedQuery);
|
||||
}
|
||||
|
||||
// 세션 ID 추가
|
||||
HttpSession session = httpRequest.getSession(true);
|
||||
request.setSessionId(session.getId());
|
||||
|
||||
// SQL 쿼리 실행 전 로깅
|
||||
log.info("쿼리 실행 요청: 타입={}, 트랜잭션ID={}, 세션ID={}",
|
||||
request.getQueryType(), request.getTransactionId(), session.getId());
|
||||
|
||||
QueryResponse response = dbQueryService.executeQuery(request);
|
||||
|
||||
// 응답 로깅
|
||||
log.info("쿼리 실행 결과: 성공={}, 행수={}, 트랜잭션ID={}",
|
||||
response.isSuccess(), response.getRowsAffected(), response.getTransactionId());
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
log.error("쿼리 실행 중 오류 발생", e);
|
||||
QueryResponse errorResponse = new QueryResponse();
|
||||
errorResponse.setSuccess(false);
|
||||
errorResponse.setMessage("쿼리 실행 중 오류: " + e.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package go.kr.project.system.execquery.exception;
|
||||
|
||||
public class TransactionException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TransactionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TransactionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package go.kr.project.system.execquery.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryRequest {
|
||||
private String query;
|
||||
private String queryType; // SELECT, INSERT, UPDATE, DELETE, COMMIT, ROLLBACK
|
||||
private String transactionId;
|
||||
private String sessionId;
|
||||
private boolean isBase64Encoded = true; // 새로운 필드 추가
|
||||
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package go.kr.project.system.execquery.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryResponse {
|
||||
private boolean success;
|
||||
private Object result;
|
||||
private String message;
|
||||
private int rowsAffected;
|
||||
private String transactionId;
|
||||
private String queryType;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package go.kr.project.system.execquery.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
@Data
|
||||
public class TransactionInfo {
|
||||
private Connection connection;
|
||||
private long lastAccessTime;
|
||||
private String sessionId;
|
||||
private long creationTime;
|
||||
}
|
||||
@ -1,328 +0,0 @@
|
||||
package go.kr.project.system.execquery.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import go.kr.project.system.execquery.config.IsolatedTransactionManager;
|
||||
import go.kr.project.system.execquery.exception.TransactionException;
|
||||
import go.kr.project.system.execquery.model.QueryRequest;
|
||||
import go.kr.project.system.execquery.model.QueryResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.sql.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class DbQueryService {
|
||||
|
||||
private final IsolatedTransactionManager transactionManager;
|
||||
|
||||
// 결과 수 제한 상수 추가
|
||||
private static final int MAX_RESULT_COUNT = 10000;
|
||||
|
||||
|
||||
/**
|
||||
* SELECT 쿼리 실행
|
||||
*/
|
||||
public QueryResponse executeSelect(QueryRequest request) {
|
||||
QueryResponse response = new QueryResponse();
|
||||
response.setQueryType("SELECT");
|
||||
|
||||
Connection conn = null;
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
try {
|
||||
// SELECT 쿼리인지 검증
|
||||
String query = request.getQuery().toUpperCase();
|
||||
if (containsDataModificationStatements(query)) {
|
||||
response.setSuccess(false);
|
||||
response.setMessage("SELECT 쿼리 타입으로 INSERT, UPDATE, DELETE 쿼리를 실행할 수 없습니다.");
|
||||
return response;
|
||||
}
|
||||
|
||||
conn = transactionManager.getConnection(request.getTransactionId());
|
||||
// SELECT 쿼리는 읽기 전용으로 설정 (트랜잭션이 없는 경우에만)
|
||||
if (request.getTransactionId() == null || request.getTransactionId().isEmpty()) {
|
||||
conn.setReadOnly(true);
|
||||
}
|
||||
ps = conn.prepareStatement(request.getQuery());
|
||||
rs = ps.executeQuery();
|
||||
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
ResultSetMetaData metaData = rs.getMetaData();
|
||||
int columnCount = metaData.getColumnCount();
|
||||
|
||||
int rowCount = 0;
|
||||
boolean resultLimited = false;
|
||||
|
||||
while (rs.next()) {
|
||||
|
||||
// 최대 결과 수 체크
|
||||
if (rowCount >= MAX_RESULT_COUNT) {
|
||||
resultLimited = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Map<String, Object> row = new LinkedHashMap<>();
|
||||
for (int i = 1; i <= columnCount; i++) {
|
||||
String columnName = metaData.getColumnLabel(i);
|
||||
int columnType = metaData.getColumnType(i);
|
||||
Object value = rs.getObject(i);
|
||||
|
||||
// DATE 타입인 경우
|
||||
if (columnType == Types.DATE && value != null) {
|
||||
Date dateValue = rs.getDate(i);
|
||||
if (dateValue != null) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
value = dateFormat.format(dateValue);
|
||||
}
|
||||
}
|
||||
// TIMESTAMP 또는 DATETIME 타입인 경우
|
||||
else if ((columnType == Types.TIMESTAMP || columnType == Types.TIMESTAMP_WITH_TIMEZONE) && value != null) {
|
||||
Timestamp timestampValue = rs.getTimestamp(i);
|
||||
if (timestampValue != null) {
|
||||
SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
value = dateTimeFormat.format(timestampValue);
|
||||
}
|
||||
}
|
||||
|
||||
row.put(columnName, value);
|
||||
}
|
||||
|
||||
resultList.add(row);
|
||||
rowCount++;
|
||||
|
||||
}
|
||||
|
||||
response.setSuccess(true);
|
||||
response.setResult(resultList);
|
||||
response.setRowsAffected(resultList.size());
|
||||
|
||||
// 결과가 제한되었을 경우 메시지 추가
|
||||
if (resultLimited) {
|
||||
response.setMessage("결과가 너무 많아 " + MAX_RESULT_COUNT + "건만 표시합니다.");
|
||||
}
|
||||
|
||||
if (request.getTransactionId() != null && !request.getTransactionId().isEmpty()) {
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("SELECT 쿼리 실행 중 오류: {}", e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage("쿼리 실행 중 오류가 발생했습니다: " + e.getMessage());
|
||||
if (request.getTransactionId() != null && !request.getTransactionId().isEmpty()) {
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
}
|
||||
} finally {
|
||||
closeResources(rs, ps, conn, request.getTransactionId() != null);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 데이터 변경 쿼리(INSERT, UPDATE, DELETE) 실행
|
||||
*/
|
||||
public QueryResponse executeUpdate(QueryRequest request) {
|
||||
QueryResponse response = new QueryResponse();
|
||||
response.setQueryType(request.getQueryType());
|
||||
|
||||
Connection conn = null;
|
||||
PreparedStatement ps = null;
|
||||
|
||||
try {
|
||||
// 트랜잭션ID가 없으면 새로 생성
|
||||
if (request.getTransactionId() == null || request.getTransactionId().isEmpty()) {
|
||||
String transactionId = transactionManager.beginTransaction();
|
||||
request.setTransactionId(transactionId);
|
||||
response.setTransactionId(transactionId);
|
||||
} else {
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
}
|
||||
|
||||
conn = transactionManager.getConnection(request.getTransactionId());
|
||||
ps = conn.prepareStatement(request.getQuery());
|
||||
|
||||
int rowsAffected = ps.executeUpdate();
|
||||
|
||||
response.setSuccess(true);
|
||||
response.setMessage("쿼리가 성공적으로 실행되었습니다. 변경사항은 커밋하기 전까지 임시 저장됩니다.");
|
||||
response.setRowsAffected(rowsAffected);
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("{} 쿼리 실행 중 오류: {}", request.getQueryType(), e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage("쿼리 실행 중 오류가 발생했습니다: " + e.getMessage());
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
} finally {
|
||||
if (ps != null) {
|
||||
try {
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("PreparedStatement 닫기 오류", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 커밋
|
||||
*/
|
||||
public QueryResponse executeCommit(QueryRequest request) {
|
||||
QueryResponse response = new QueryResponse();
|
||||
response.setQueryType("COMMIT");
|
||||
|
||||
try {
|
||||
if (request.getTransactionId() == null || request.getTransactionId().isEmpty()) {
|
||||
response.setSuccess(false);
|
||||
response.setMessage("커밋할 트랜잭션 ID가 필요합니다.");
|
||||
return response;
|
||||
}
|
||||
|
||||
transactionManager.commitTransaction(request.getTransactionId());
|
||||
|
||||
response.setSuccess(true);
|
||||
response.setMessage("트랜잭션이 성공적으로 커밋되었습니다.");
|
||||
|
||||
} catch (TransactionException e) {
|
||||
log.error("트랜잭션 커밋 권한 오류: {}", e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage(e.getMessage());
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
} catch (SQLException e) {
|
||||
log.error("트랜잭션 커밋 중 오류: {}", e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage("트랜잭션 커밋 중 오류가 발생했습니다: " + e.getMessage());
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 트랜잭션 롤백
|
||||
*/
|
||||
public QueryResponse executeRollback(QueryRequest request) {
|
||||
QueryResponse response = new QueryResponse();
|
||||
response.setQueryType("ROLLBACK");
|
||||
|
||||
try {
|
||||
if (request.getTransactionId() == null || request.getTransactionId().isEmpty()) {
|
||||
response.setSuccess(false);
|
||||
response.setMessage("롤백할 트랜잭션 ID가 필요합니다.");
|
||||
return response;
|
||||
}
|
||||
|
||||
transactionManager.rollbackTransaction(request.getTransactionId());
|
||||
|
||||
response.setSuccess(true);
|
||||
response.setMessage("트랜잭션이 성공적으로 롤백되었습니다.");
|
||||
|
||||
} catch (TransactionException e) {
|
||||
log.error("트랜잭션 롤백 권한 오류: {}", e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage(e.getMessage());
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
} catch (SQLException e) {
|
||||
log.error("트랜잭션 롤백 중 오류: {}", e.getMessage(), e);
|
||||
response.setSuccess(false);
|
||||
response.setMessage("트랜잭션 롤백 중 오류가 발생했습니다: " + e.getMessage());
|
||||
response.setTransactionId(request.getTransactionId());
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 쿼리 타입에 따라 적절한 실행 메서드 호출
|
||||
*/
|
||||
public QueryResponse executeQuery(QueryRequest request) {
|
||||
String queryType = request.getQueryType().toUpperCase();
|
||||
|
||||
// ObjectMapper 생성 및 설정
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
|
||||
|
||||
// 요청 객체를 다시 파싱 (필요한 경우)
|
||||
// 예: 요청 객체의 쿼리 문자열에 줄바꿈이 포함되어 있을 경우
|
||||
String requestJson = null;
|
||||
QueryRequest sanitizedRequest = null;
|
||||
try {
|
||||
requestJson = objectMapper.writeValueAsString(request);
|
||||
sanitizedRequest = objectMapper.readValue(requestJson, QueryRequest.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
switch (queryType) {
|
||||
case "SELECT":
|
||||
return executeSelect(sanitizedRequest);
|
||||
case "INSERT":
|
||||
case "UPDATE":
|
||||
case "DELETE":
|
||||
return executeUpdate(sanitizedRequest);
|
||||
case "COMMIT":
|
||||
return executeCommit(request);
|
||||
case "ROLLBACK":
|
||||
return executeRollback(request);
|
||||
default:
|
||||
QueryResponse response = new QueryResponse();
|
||||
response.setSuccess(false);
|
||||
response.setMessage("지원하지 않는 쿼리 타입입니다. SELECT, INSERT, UPDATE, DELETE, COMMIT, ROLLBACK만 지원합니다.");
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 쿼리에 데이터 수정 구문(INSERT, UPDATE, DELETE)이 포함되어 있는지 확인
|
||||
*/
|
||||
private boolean containsDataModificationStatements(String query) {
|
||||
// 정규식을 사용하여 INSERT, UPDATE, DELETE 키워드가 단어 경계에 있는지 확인
|
||||
return query.matches("(?i).*\\bINSERT\\b.*") ||
|
||||
query.matches("(?i).*\\bUPDATE\\b.*") ||
|
||||
query.matches("(?i).*\\bDELETE\\b.*");
|
||||
}
|
||||
|
||||
/**
|
||||
* 리소스 정리
|
||||
*/
|
||||
private void closeResources(ResultSet rs, PreparedStatement ps, Connection conn, boolean keepConnection) {
|
||||
if (rs != null) {
|
||||
try {
|
||||
rs.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("ResultSet 닫기 오류", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (ps != null) {
|
||||
try {
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("PreparedStatement 닫기 오류", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (conn != null && !keepConnection) {
|
||||
try {
|
||||
// 연결을 닫기 전에 읽기 전용 모드를 해제
|
||||
if (conn.isReadOnly()) {
|
||||
conn.setReadOnly(false);
|
||||
}
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("Connection 닫기 오류", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,177 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.BatchFileDataMapper">
|
||||
|
||||
<!-- 배치 파일 데이터 등록 -->
|
||||
<insert id="insertBatchFileData" parameterType="BatchFileDataVO">
|
||||
<selectKey keyProperty="fileDataId" resultType="String" order="BEFORE">
|
||||
SELECT CONCAT('BFDT', LPAD(NEXTVAL(seq_batch_file_data_id), 16, '0'))
|
||||
</selectKey>
|
||||
INSERT INTO TB_BATCH_FILE_DATA (
|
||||
FILE_DATA_ID,
|
||||
FILE_NM,
|
||||
LINE_NUMBER,
|
||||
COLUMN1,
|
||||
COLUMN2,
|
||||
COLUMN3,
|
||||
COLUMN4,
|
||||
COLUMN5,
|
||||
RAW_DATA,
|
||||
PROCESS_STATUS,
|
||||
ERROR_MESSAGE,
|
||||
PROCESS_DTTM,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES (
|
||||
#{fileDataId},
|
||||
#{fileNm},
|
||||
#{lineNumber},
|
||||
#{column1},
|
||||
#{column2},
|
||||
#{column3},
|
||||
#{column4},
|
||||
#{column5},
|
||||
#{rawData},
|
||||
#{processStatus},
|
||||
#{errorMessage},
|
||||
#{processDttm},
|
||||
NOW(),
|
||||
#{rgtr},
|
||||
NOW(),
|
||||
#{mdfr}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 배치 파일 데이터 수정 -->
|
||||
<update id="updateBatchFileData" parameterType="BatchFileDataVO">
|
||||
UPDATE TB_BATCH_FILE_DATA
|
||||
SET
|
||||
COLUMN1 = #{column1},
|
||||
COLUMN2 = #{column2},
|
||||
COLUMN3 = #{column3},
|
||||
COLUMN4 = #{column4},
|
||||
COLUMN5 = #{column5},
|
||||
RAW_DATA = #{rawData},
|
||||
PROCESS_STATUS = #{processStatus},
|
||||
ERROR_MESSAGE = #{errorMessage},
|
||||
PROCESS_DTTM = #{processDttm},
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = #{mdfr}
|
||||
WHERE FILE_DATA_ID = #{fileDataId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 파일 데이터 삭제 -->
|
||||
<delete id="deleteBatchFileData" parameterType="String">
|
||||
DELETE FROM tb_batch_file_data
|
||||
WHERE FILE_DATA_ID = #{fileDataId}
|
||||
</delete>
|
||||
|
||||
<!-- 배치 파일 데이터 조회 -->
|
||||
<select id="selectBatchFileData" parameterType="String" resultType="BatchFileDataVO">
|
||||
SELECT
|
||||
file_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data
|
||||
WHERE file_data_id = #{fileDataId}
|
||||
</select>
|
||||
|
||||
<!-- 배치 파일 데이터 총 개수 조회 -->
|
||||
<select id="selectBatchFileDataTotalCount" parameterType="BatchFileDataVO" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM tb_batch_file_data
|
||||
WHERE 1=1
|
||||
<if test="searchFileNm != null and searchFileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{searchFileNm}, '%')
|
||||
</if>
|
||||
<if test="searchProcessStatus != null and searchProcessStatus != ''">
|
||||
AND process_status = #{searchProcessStatus}
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(process_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(process_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 배치 파일 데이터 목록 조회 -->
|
||||
<select id="selectBatchFileDataList" parameterType="BatchFileDataVO" resultType="BatchFileDataVO">
|
||||
SELECT
|
||||
file_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data
|
||||
WHERE 1=1
|
||||
<if test="searchFileNm != null and searchFileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{searchFileNm}, '%')
|
||||
</if>
|
||||
<if test="searchProcessStatus != null and searchProcessStatus != ''">
|
||||
AND process_status = #{searchProcessStatus}
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(process_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(process_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
ORDER BY process_dttm DESC, line_number ASC
|
||||
<if test="pagingYn == 'Y'">
|
||||
LIMIT #{startIndex}, #{recordCountPerPage}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 파일명으로 배치 파일 데이터 목록 조회 -->
|
||||
<select id="selectBatchFileDataByFileNm" parameterType="String" resultType="BatchFileDataVO">
|
||||
SELECT
|
||||
file_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data
|
||||
WHERE file_nm = #{fileNm}
|
||||
ORDER BY line_number ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -1,165 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.BatchFileDataSuccessMapper">
|
||||
|
||||
<!-- 배치 파일 성공 데이터 등록 -->
|
||||
<insert id="insertBatchFileDataSuccess" parameterType="BatchFileDataSuccessVO">
|
||||
<selectKey keyProperty="successDataId" resultType="String" order="BEFORE">
|
||||
SELECT CONCAT('BSDT', LPAD(NEXTVAL(seq_batch_file_data_success_id), 16, '0'))
|
||||
</selectKey>
|
||||
INSERT INTO tb_batch_file_data_success (
|
||||
success_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES (
|
||||
#{successDataId},
|
||||
#{fileNm},
|
||||
#{lineNumber},
|
||||
#{column1},
|
||||
#{column2},
|
||||
#{column3},
|
||||
#{column4},
|
||||
#{column5},
|
||||
#{rawData},
|
||||
#{processDttm},
|
||||
NOW(),
|
||||
#{rgtr},
|
||||
NOW(),
|
||||
#{mdfr}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 배치 파일 성공 데이터 수정 -->
|
||||
<update id="updateBatchFileDataSuccess" parameterType="BatchFileDataSuccessVO">
|
||||
UPDATE tb_batch_file_data_success
|
||||
SET
|
||||
column1 = #{column1},
|
||||
column2 = #{column2},
|
||||
column3 = #{column3},
|
||||
column4 = #{column4},
|
||||
column5 = #{column5},
|
||||
raw_data = #{rawData},
|
||||
process_dttm = #{processDttm},
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = #{mdfr}
|
||||
WHERE success_data_id = #{successDataId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 파일 성공 데이터 삭제 -->
|
||||
<delete id="deleteBatchFileDataSuccess" parameterType="String">
|
||||
DELETE FROM tb_batch_file_data_success
|
||||
WHERE success_data_id = #{successDataId}
|
||||
</delete>
|
||||
|
||||
<!-- 배치 파일 성공 데이터 조회 -->
|
||||
<select id="selectBatchFileDataSuccess" parameterType="String" resultType="BatchFileDataSuccessVO">
|
||||
SELECT
|
||||
success_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data_success
|
||||
WHERE success_data_id = #{successDataId}
|
||||
</select>
|
||||
|
||||
<!-- 배치 파일 성공 데이터 총 개수 조회 -->
|
||||
<select id="selectBatchFileDataSuccessTotalCount" parameterType="BatchFileDataSuccessVO" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM tb_batch_file_data_success
|
||||
WHERE 1=1
|
||||
<if test="searchFileNm != null and searchFileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{searchFileNm}, '%')
|
||||
</if>
|
||||
<if test="searchColumn1 != null and searchColumn1 != ''">
|
||||
AND column1 LIKE CONCAT('%', #{searchColumn1}, '%')
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(process_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(process_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 배치 파일 성공 데이터 목록 조회 -->
|
||||
<select id="selectBatchFileDataSuccessList" parameterType="BatchFileDataSuccessVO" resultType="BatchFileDataSuccessVO">
|
||||
SELECT
|
||||
success_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data_success
|
||||
WHERE 1=1
|
||||
<if test="searchFileNm != null and searchFileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{searchFileNm}, '%')
|
||||
</if>
|
||||
<if test="searchColumn1 != null and searchColumn1 != ''">
|
||||
AND column1 LIKE CONCAT('%', #{searchColumn1}, '%')
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(process_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(process_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
ORDER BY process_dttm DESC, line_number ASC
|
||||
<if test="pagingYn == 'Y'">
|
||||
LIMIT #{startIndex}, #{recordCountPerPage}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 파일명으로 배치 파일 성공 데이터 목록 조회 -->
|
||||
<select id="selectBatchFileDataSuccessByFileNm" parameterType="String" resultType="BatchFileDataSuccessVO">
|
||||
SELECT
|
||||
success_data_id,
|
||||
file_nm,
|
||||
line_number,
|
||||
column1,
|
||||
column2,
|
||||
column3,
|
||||
column4,
|
||||
column5,
|
||||
raw_data,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_data_success
|
||||
WHERE file_nm = #{fileNm}
|
||||
ORDER BY line_number ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -1,223 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.BatchFileRetryMapper">
|
||||
|
||||
<!-- 재처리 이력 등록 -->
|
||||
<insert id="insertBatchFileRetry" parameterType="BatchFileRetryVO">
|
||||
<selectKey keyProperty="retryId" resultType="String" order="BEFORE">
|
||||
SELECT CONCAT('BFRT', LPAD(NEXTVAL(seq_batch_file_retry_id), 16, '0'))
|
||||
</selectKey>
|
||||
INSERT INTO tb_batch_file_retry (
|
||||
retry_id,
|
||||
original_file_nm,
|
||||
retry_file_nm,
|
||||
retry_cnt,
|
||||
max_retry_cnt,
|
||||
retry_status,
|
||||
error_type,
|
||||
error_message,
|
||||
retry_dttm,
|
||||
next_retry_dttm,
|
||||
completed_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES (
|
||||
#{retryId},
|
||||
#{originalFileNm},
|
||||
#{retryFileNm},
|
||||
#{retryCnt},
|
||||
#{maxRetryCnt},
|
||||
#{retryStatus},
|
||||
#{errorType},
|
||||
#{errorMessage},
|
||||
#{retryDttm},
|
||||
#{nextRetryDttm},
|
||||
#{completedDttm},
|
||||
NOW(),
|
||||
#{rgtr},
|
||||
NOW(),
|
||||
#{mdfr}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 재처리 이력 수정 -->
|
||||
<update id="updateBatchFileRetry" parameterType="BatchFileRetryVO">
|
||||
UPDATE tb_batch_file_retry
|
||||
SET retry_file_nm = #{retryFileNm},
|
||||
retry_count = #{retryCount},
|
||||
retry_status = #{retryStatus},
|
||||
<if test = 'retryStatus == "SUCCESS"'>
|
||||
error_type = null,
|
||||
error_message = null,
|
||||
</if>
|
||||
<if test = 'retryStatus != "SUCCESS"'>
|
||||
error_type = #{errorType},
|
||||
error_message = #{errorMessage},
|
||||
</if>
|
||||
retry_dttm = #{retryDttm},
|
||||
next_retry_dttm = #{nextRetryDttm},
|
||||
completed_dttm = #{completedDttm},
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = #{mdfr}
|
||||
WHERE retry_id = #{retryId}
|
||||
</update>
|
||||
|
||||
<!-- 재처리 이력 삭제 -->
|
||||
<delete id="deleteBatchFileRetry" parameterType="String">
|
||||
DELETE FROM tb_batch_file_retry
|
||||
WHERE retry_id = #{retryId}
|
||||
</delete>
|
||||
|
||||
<!-- 재처리 이력 조회 -->
|
||||
<select id="selectBatchFileRetry" parameterType="String" resultType="BatchFileRetryVO">
|
||||
SELECT retry_id,
|
||||
original_file_nm,
|
||||
retry_file_nm,
|
||||
retry_cnt,
|
||||
max_retry_cnt,
|
||||
retry_status,
|
||||
error_type,
|
||||
error_message,
|
||||
retry_dttm,
|
||||
next_retry_dttm,
|
||||
completed_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_retry
|
||||
WHERE retry_id = #{retryId}
|
||||
</select>
|
||||
|
||||
<!-- 재처리 이력 목록 총 개수 조회 -->
|
||||
<select id="selectBatchFileRetryListTotalCount" parameterType="BatchFileRetryVO" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM tb_batch_file_retry
|
||||
<where>
|
||||
<if test="originalFileNm != null and originalFileNm != ''">
|
||||
AND original_file_nm LIKE CONCAT('%', #{originalFileNm}, '%')
|
||||
</if>
|
||||
<if test="retryStatus != null and retryStatus != ''">
|
||||
AND retry_status = #{retryStatus}
|
||||
</if>
|
||||
<if test="errorType != null and errorType != ''">
|
||||
AND error_type = #{errorType}
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(retry_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(retry_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 재처리 이력 목록 조회 -->
|
||||
<select id="selectBatchFileRetryList" parameterType="BatchFileRetryVO" resultType="BatchFileRetryVO">
|
||||
SELECT retry_id,
|
||||
original_file_nm,
|
||||
retry_file_nm,
|
||||
retry_cnt,
|
||||
max_retry_cnt,
|
||||
retry_status,
|
||||
error_type,
|
||||
error_message,
|
||||
retry_dttm,
|
||||
next_retry_dttm,
|
||||
completed_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_retry
|
||||
<where>
|
||||
<if test="originalFileNm != null and originalFileNm != ''">
|
||||
AND original_file_nm LIKE CONCAT('%', #{originalFileNm}, '%')
|
||||
</if>
|
||||
<if test="retryStatus != null and retryStatus != ''">
|
||||
AND retry_status = #{retryStatus}
|
||||
</if>
|
||||
<if test="errorType != null and errorType != ''">
|
||||
AND error_type = #{errorType}
|
||||
</if>
|
||||
<if test="searchStartDate != null and searchStartDate != ''">
|
||||
AND DATE(retry_dttm) >= #{searchStartDate}
|
||||
</if>
|
||||
<if test="searchEndDate != null and searchEndDate != ''">
|
||||
AND DATE(retry_dttm) <= #{searchEndDate}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY retry_dttm DESC
|
||||
<if test="pagingYn == 'Y'">
|
||||
LIMIT #{recordCountPerPage} OFFSET #{firstIndex}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 원본 파일명으로 재처리 이력 조회 -->
|
||||
<select id="selectBatchFileRetryByOriginalFileNm" parameterType="String" resultType="BatchFileRetryVO">
|
||||
SELECT retry_id,
|
||||
original_file_nm,
|
||||
retry_file_nm,
|
||||
retry_cnt,
|
||||
max_retry_cnt,
|
||||
retry_status,
|
||||
error_type,
|
||||
error_message,
|
||||
retry_dttm,
|
||||
next_retry_dttm,
|
||||
completed_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_retry
|
||||
WHERE original_file_nm = #{originalFileNm}
|
||||
ORDER BY retry_dttm DESC
|
||||
</select>
|
||||
|
||||
<!-- 재처리 대상 파일 목록 조회 -->
|
||||
<select id="selectRetryTargetFiles" resultType="BatchFileRetryVO">
|
||||
SELECT retry_id,
|
||||
original_file_nm,
|
||||
retry_file_nm,
|
||||
retry_cnt,
|
||||
max_retry_cnt,
|
||||
retry_status,
|
||||
error_type,
|
||||
error_message,
|
||||
retry_dttm,
|
||||
next_retry_dttm,
|
||||
completed_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_file_retry
|
||||
WHERE retry_status = 'PENDING'
|
||||
AND retry_cnt < max_retry_cnt
|
||||
AND (next_retry_dttm IS NULL OR next_retry_dttm <= NOW())
|
||||
ORDER BY retry_dttm ASC
|
||||
</select>
|
||||
|
||||
<!-- 재처리 상태 업데이트 -->
|
||||
<update id="updateRetryStatus">
|
||||
UPDATE tb_batch_file_retry
|
||||
SET retry_status = #{retryStatus},
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = 'BATCH_SYSTEM'
|
||||
WHERE retry_id = #{retryId}
|
||||
</update>
|
||||
|
||||
<!-- 재처리 횟수 증가 -->
|
||||
<update id="incrementRetryCnt">
|
||||
UPDATE tb_batch_file_retry
|
||||
SET retry_cnt = retry_cnt + 1,
|
||||
retry_dttm = NOW(),
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = 'BATCH_SYSTEM'
|
||||
WHERE retry_id = #{retryId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@ -1,363 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.BatchJobMapper">
|
||||
|
||||
<!-- 배치 작업 정보 등록 -->
|
||||
<insert id="insertBatchJobInfo" parameterType="BatchJobInfoVO">
|
||||
INSERT INTO TB_BATCH_JOB_INFO (
|
||||
JOB_ID,
|
||||
JOB_NM,
|
||||
JOB_GROUP,
|
||||
JOB_CLASS,
|
||||
CRON_EXPRESSION,
|
||||
JOB_DC,
|
||||
STATUS_CD,
|
||||
LAST_EXECUTION_ID,
|
||||
REG_DTTM,
|
||||
MDFCN_DTTM
|
||||
) VALUES (
|
||||
#{jobId},
|
||||
#{jobNm},
|
||||
#{jobGroup},
|
||||
#{jobClass},
|
||||
#{cronExpression},
|
||||
#{jobDc},
|
||||
#{statusCd},
|
||||
#{lastExecutionId},
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 배치 작업 정보 수정 -->
|
||||
<update id="updateBatchJobInfo" parameterType="BatchJobInfoVO">
|
||||
UPDATE TB_BATCH_JOB_INFO
|
||||
SET
|
||||
JOB_NM = #{jobNm},
|
||||
JOB_GROUP = #{jobGroup},
|
||||
JOB_CLASS = #{jobClass},
|
||||
CRON_EXPRESSION = #{cronExpression},
|
||||
JOB_DC = #{jobDc},
|
||||
STATUS_CD = #{statusCd},
|
||||
MDFCN_DTTM = NOW()
|
||||
WHERE
|
||||
JOB_ID = #{jobId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 작업 정보 삭제 -->
|
||||
<delete id="deleteBatchJobInfo" parameterType="String">
|
||||
DELETE FROM TB_BATCH_JOB_INFO
|
||||
WHERE JOB_ID = #{jobId}
|
||||
</delete>
|
||||
|
||||
<!-- 배치 작업 정보 조회 -->
|
||||
<select id="selectBatchJobInfo" parameterType="String" resultType="BatchJobInfoVO">
|
||||
SELECT
|
||||
A.JOB_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.JOB_CLASS,
|
||||
A.CRON_EXPRESSION,
|
||||
A.JOB_DC,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as statusNm,
|
||||
A.LAST_EXECUTION_ID,
|
||||
A.REG_DTTM,
|
||||
A.MDFCN_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_INFO A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_JOB_INFO_STATUS_CD'
|
||||
WHERE
|
||||
A.JOB_ID = #{jobId}
|
||||
</select>
|
||||
|
||||
<!-- 배치 작업 정보를 이름과 그룹으로 조회 -->
|
||||
<select id="selectBatchJobInfoByNmAndGroup" resultType="BatchJobInfoVO">
|
||||
SELECT
|
||||
A.JOB_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.JOB_CLASS,
|
||||
A.CRON_EXPRESSION,
|
||||
A.JOB_DC,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as statusNm,
|
||||
A.LAST_EXECUTION_ID,
|
||||
A.REG_DTTM,
|
||||
A.MDFCN_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_INFO A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_JOB_INFO_STATUS_CD'
|
||||
WHERE
|
||||
A.JOB_NM = #{jobNm}
|
||||
AND A.JOB_GROUP = #{jobGroup}
|
||||
</select>
|
||||
|
||||
<!-- 모든 배치 작업 정보 조회 -->
|
||||
<select id="selectBatchJobInfoList" resultType="BatchJobInfoVO" parameterType="BatchJobExecutionVO">
|
||||
SELECT
|
||||
A.JOB_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.JOB_CLASS,
|
||||
A.CRON_EXPRESSION,
|
||||
A.JOB_DC,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as statusNm,
|
||||
A.LAST_EXECUTION_ID,
|
||||
A.REG_DTTM,
|
||||
A.MDFCN_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_INFO A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_JOB_INFO_STATUS_CD'
|
||||
WHERE 1=1
|
||||
<if test="searchStatusCd != null and searchStatusCd != ''">
|
||||
AND A.STATUS_CD = #{searchStatusCd}
|
||||
</if>
|
||||
ORDER BY
|
||||
A.REG_DTTM DESC
|
||||
</select>
|
||||
|
||||
<!-- 배치 작업 실행 결과 등록 -->
|
||||
<insert id="insertBatchJobExecution" parameterType="BatchJobExecutionVO">
|
||||
INSERT INTO TB_BATCH_JOB_EXECUTION (
|
||||
EXECUTION_ID,
|
||||
JOB_NM,
|
||||
JOB_GROUP,
|
||||
START_DTTM,
|
||||
END_DTTM,
|
||||
STATUS_CD,
|
||||
EXIT_CD,
|
||||
EXIT_MESSAGE,
|
||||
SERVER_INFO,
|
||||
REG_DTTM
|
||||
) VALUES (
|
||||
#{executionId},
|
||||
#{jobNm},
|
||||
#{jobGroup},
|
||||
#{startDttm},
|
||||
#{endDttm},
|
||||
#{statusCd},
|
||||
#{exitCd},
|
||||
#{exitMessage},
|
||||
#{serverInfo},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 배치 작업 실행 결과 수정 -->
|
||||
<update id="updateBatchJobExecution" parameterType="BatchJobExecutionVO">
|
||||
UPDATE TB_BATCH_JOB_EXECUTION
|
||||
SET
|
||||
END_DTTM = #{endDttm},
|
||||
STATUS_CD = #{statusCd},
|
||||
EXIT_CD = #{exitCd},
|
||||
EXIT_MESSAGE = #{exitMessage},
|
||||
SERVER_INFO = #{serverInfo}
|
||||
WHERE
|
||||
EXECUTION_ID = #{executionId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 작업 실행 결과 조회 -->
|
||||
<select id="selectBatchJobExecution" parameterType="String" resultType="BatchJobExecutionVO">
|
||||
SELECT
|
||||
A.EXECUTION_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.START_DTTM,
|
||||
A.END_DTTM,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as statusNm,
|
||||
A.EXIT_CD,
|
||||
C.CD_NM as exitCdNm,
|
||||
A.EXIT_MESSAGE,
|
||||
A.SERVER_INFO,
|
||||
A.REG_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_EXECUTION A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_EXEC_STATUS_CD'
|
||||
LEFT JOIN
|
||||
tb_cd_detail C ON A.EXIT_CD = C.CD_ID AND C.CD_GROUP_ID = 'BATCH_EXIT_CD'
|
||||
WHERE
|
||||
A.EXECUTION_ID = #{executionId}
|
||||
</select>
|
||||
|
||||
<!-- 배치 작업의 실행 결과 목록 조회 -->
|
||||
<select id="selectBatchJobExecutionTotalCount" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM
|
||||
TB_BATCH_JOB_EXECUTION A
|
||||
WHERE
|
||||
A.JOB_NM = #{jobNm}
|
||||
AND A.JOB_GROUP = #{jobGroup}
|
||||
<if test="searchStatusCd != null and searchStatusCd != ''">
|
||||
AND A.STATUS_CD = #{searchStatusCd}
|
||||
</if>
|
||||
<if test="searchExitCd != null and searchExitCd != ''">
|
||||
<choose>
|
||||
<when test="searchExitCd == 'UNKNOWN'">
|
||||
AND (A.EXIT_CD = #{searchExitCd} OR A.EXIT_CD IS NULL)
|
||||
</when>
|
||||
<otherwise>
|
||||
AND A.EXIT_CD = #{searchExitCd}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
<if test='searchStartDt != null and searchEndDt != null'>
|
||||
AND A.START_DTTM BETWEEN STR_TO_DATE(CONCAT(#{searchStartDt},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
|
||||
AND STR_TO_DATE(CONCAT(#{searchEndDt},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
|
||||
</if>
|
||||
</select>
|
||||
<!-- 배치 작업의 실행 결과 목록 조회 -->
|
||||
<select id="selectBatchJobExecutionList" resultType="BatchJobExecutionVO">
|
||||
SELECT
|
||||
A.EXECUTION_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.START_DTTM,
|
||||
A.END_DTTM,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as STATUS_NM,
|
||||
A.EXIT_CD,
|
||||
C.CD_NM as EXIT_CD_NM,
|
||||
A.EXIT_MESSAGE,
|
||||
A.SERVER_INFO,
|
||||
A.REG_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_EXECUTION A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_EXEC_STATUS_CD'
|
||||
LEFT JOIN
|
||||
tb_cd_detail C ON A.EXIT_CD = C.CD_ID AND C.CD_GROUP_ID = 'BATCH_EXIT_CD'
|
||||
WHERE
|
||||
A.JOB_NM = #{jobNm}
|
||||
AND A.JOB_GROUP = #{jobGroup}
|
||||
<if test="searchStatusCd != null and searchStatusCd != ''">
|
||||
AND A.STATUS_CD = #{searchStatusCd}
|
||||
</if>
|
||||
<if test="searchExitCd != null and searchExitCd != ''">
|
||||
<choose>
|
||||
<when test="searchExitCd == 'UNKNOWN'">
|
||||
AND (A.EXIT_CD = #{searchExitCd} OR A.EXIT_CD IS NULL)
|
||||
</when>
|
||||
<otherwise>
|
||||
AND A.EXIT_CD = #{searchExitCd}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
<if test='searchStartDt != null and searchEndDt != null'>
|
||||
AND A.START_DTTM BETWEEN STR_TO_DATE(CONCAT(#{searchStartDt},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
|
||||
AND STR_TO_DATE(CONCAT(#{searchEndDt},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
|
||||
</if>
|
||||
ORDER BY
|
||||
A.START_DTTM DESC
|
||||
<if test="pagingYn != null and pagingYn.toString() == 'Y'.toString()">
|
||||
LIMIT #{startIndex}, #{perPage}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 배치 작업의 마지막 실행 결과 조회 -->
|
||||
<select id="selectLastBatchJobExecution" resultType="BatchJobExecutionVO">
|
||||
SELECT
|
||||
A.EXECUTION_ID,
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP,
|
||||
A.START_DTTM,
|
||||
A.END_DTTM,
|
||||
A.STATUS_CD,
|
||||
B.CD_NM as statusNm,
|
||||
A.EXIT_CD,
|
||||
C.CD_NM as exitCdNm,
|
||||
A.EXIT_MESSAGE,
|
||||
A.SERVER_INFO,
|
||||
A.REG_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_EXECUTION A
|
||||
LEFT JOIN
|
||||
tb_cd_detail B ON A.STATUS_CD = B.CD_ID AND B.CD_GROUP_ID = 'BATCH_EXEC_STATUS_CD'
|
||||
LEFT JOIN
|
||||
tb_cd_detail C ON A.EXIT_CD = C.CD_ID AND C.CD_GROUP_ID = 'BATCH_EXIT_CD'
|
||||
WHERE
|
||||
A.JOB_NM = #{jobNm}
|
||||
AND A.JOB_GROUP = #{jobGroup}
|
||||
ORDER BY
|
||||
A.START_DTTM DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 배치 작업 상태 업데이트 -->
|
||||
<update id="updateBatchJobStatus">
|
||||
UPDATE TB_BATCH_JOB_INFO
|
||||
SET
|
||||
STATUS_CD = #{statusCd},
|
||||
MDFCN_DTTM = NOW()
|
||||
WHERE
|
||||
JOB_ID = #{jobId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 작업의 마지막 실행 ID 업데이트 -->
|
||||
<update id="updateBatchJobLastExecution">
|
||||
UPDATE TB_BATCH_JOB_INFO
|
||||
SET
|
||||
LAST_EXECUTION_ID = #{executionId},
|
||||
MDFCN_DTTM = NOW()
|
||||
WHERE
|
||||
JOB_ID = #{jobId}
|
||||
</update>
|
||||
|
||||
<!-- 배치 작업 실행 로그 등록 -->
|
||||
<insert id="insertBatchJobLog">
|
||||
INSERT INTO TB_BATCH_JOB_LOG (
|
||||
LOG_ID,
|
||||
EXECUTION_ID,
|
||||
LOG_DTTM,
|
||||
LOG_LEVEL,
|
||||
LOG_MESSAGE,
|
||||
REG_DTTM
|
||||
) VALUES (
|
||||
CONCAT('BJLG', LPAD(NEXTVAL(seq_batch_job_log_id), 16, '0')),
|
||||
#{executionId},
|
||||
NOW(),
|
||||
#{logLevel},
|
||||
#{logMessage},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 배치 작업 실행 로그 목록 조회 -->
|
||||
<select id="selectBatchJobLogList" parameterType="String" resultType="BatchJobLogVO">
|
||||
SELECT
|
||||
LOG_ID,
|
||||
EXECUTION_ID,
|
||||
LOG_DTTM,
|
||||
LOG_LEVEL,
|
||||
LOG_MESSAGE,
|
||||
REG_DTTM
|
||||
FROM
|
||||
TB_BATCH_JOB_LOG
|
||||
WHERE
|
||||
EXECUTION_ID = #{executionId}
|
||||
<if test="searchLogLevel != null and searchLogLevel != ''">
|
||||
AND LOG_LEVEL = #{searchLogLevel}
|
||||
</if>
|
||||
ORDER BY
|
||||
LOG_DTTM ASC
|
||||
</select>
|
||||
|
||||
<!-- 최근 48시간 내 실패한 배치 작업 목록 조회 -->
|
||||
<select id="selectRecentlyFailedJobs" resultType="BatchJobInfoVO">
|
||||
SELECT DISTINCT
|
||||
A.JOB_NM,
|
||||
A.JOB_GROUP
|
||||
FROM
|
||||
TB_BATCH_JOB_EXECUTION A
|
||||
WHERE
|
||||
(A.EXIT_CD != 'COMPLETED')
|
||||
AND A.START_DTTM >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -1,211 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.ZipFileDetailLogMapper">
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 ID 생성 -->
|
||||
<select id="generateZipFileDetailLogId" resultType="String">
|
||||
SELECT CONCAT('ZFDL', LPAD(NEXTVAL(seq_batch_zip_file_detail_log_id), 16, '0'))
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 등록 -->
|
||||
<insert id="insertZipFileDetailLog" parameterType="ZipFileDetailLogVO">
|
||||
<selectKey keyProperty="detailLogId" resultType="String" order="BEFORE">
|
||||
SELECT CONCAT('ZFDL', LPAD(NEXTVAL(seq_batch_zip_file_detail_log_id), 16, '0'))
|
||||
</selectKey>
|
||||
INSERT INTO tb_batch_zip_file_detail_log (
|
||||
detail_log_id,
|
||||
log_id,
|
||||
file_nm,
|
||||
file_path,
|
||||
file_size,
|
||||
file_type,
|
||||
image_yn,
|
||||
corrupted_yn,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES (
|
||||
#{detailLogId},
|
||||
#{logId},
|
||||
#{fileNm},
|
||||
#{filePath},
|
||||
#{fileSize},
|
||||
#{fileType},
|
||||
#{imageYn},
|
||||
#{corruptedYn},
|
||||
#{processStatus},
|
||||
#{errorMessage},
|
||||
#{processDttm},
|
||||
NOW(),
|
||||
#{rgtr},
|
||||
NOW(),
|
||||
#{mdfr}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 목록 일괄 등록 -->
|
||||
<insert id="insertZipFileDetailLogList" parameterType="java.util.List">
|
||||
INSERT INTO tb_batch_zip_file_detail_log (
|
||||
detail_log_id,
|
||||
log_id,
|
||||
file_nm,
|
||||
file_path,
|
||||
file_size,
|
||||
file_type,
|
||||
image_yn,
|
||||
corrupted_yn,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
CONCAT('ZFDL', LPAD(NEXTVAL(seq_batch_zip_file_detail_log_id), 16, '0')),
|
||||
#{item.logId},
|
||||
#{item.fileNm},
|
||||
#{item.filePath},
|
||||
#{item.fileSize},
|
||||
#{item.fileType},
|
||||
#{item.imageYn},
|
||||
#{item.corruptedYn},
|
||||
#{item.processStatus},
|
||||
#{item.errorMessage},
|
||||
#{item.processDttm},
|
||||
NOW(),
|
||||
#{item.rgtr},
|
||||
NOW(),
|
||||
#{item.mdfr}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 삭제 -->
|
||||
<delete id="deleteZipFileDetailLog" parameterType="String">
|
||||
DELETE FROM tb_batch_zip_file_detail_log
|
||||
WHERE detail_log_id = #{detailLogId}
|
||||
</delete>
|
||||
|
||||
<!-- 로그 ID로 ZIP 파일 처리 상세 로그 삭제 -->
|
||||
<delete id="deleteZipFileDetailLogByLogId" parameterType="String">
|
||||
DELETE FROM tb_batch_zip_file_detail_log
|
||||
WHERE log_id = #{logId}
|
||||
</delete>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 조회 -->
|
||||
<select id="selectZipFileDetailLog" parameterType="String" resultType="ZipFileDetailLogVO">
|
||||
SELECT
|
||||
detail_log_id,
|
||||
log_id,
|
||||
file_nm,
|
||||
file_path,
|
||||
file_size,
|
||||
file_type,
|
||||
image_yn,
|
||||
corrupted_yn,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_zip_file_detail_log
|
||||
WHERE detail_log_id = #{detailLogId}
|
||||
</select>
|
||||
|
||||
<!-- 로그 ID로 ZIP 파일 처리 상세 로그 목록 조회 -->
|
||||
<select id="selectZipFileDetailLogListByLogId" parameterType="String" resultType="ZipFileDetailLogVO">
|
||||
SELECT
|
||||
detail_log_id,
|
||||
log_id,
|
||||
file_nm,
|
||||
file_path,
|
||||
file_size,
|
||||
file_type,
|
||||
image_yn,
|
||||
corrupted_yn,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_zip_file_detail_log
|
||||
WHERE log_id = #{logId}
|
||||
ORDER BY process_dttm ASC
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 목록 총 개수 조회 -->
|
||||
<select id="selectZipFileDetailLogListTotalCount" parameterType="ZipFileDetailLogVO" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM tb_batch_zip_file_detail_log
|
||||
WHERE 1=1
|
||||
<if test="logId != null and logId != ''">
|
||||
AND log_id = #{logId}
|
||||
</if>
|
||||
<if test="fileNm != null and fileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{fileNm}, '%')
|
||||
</if>
|
||||
<if test="processStatus != null and processStatus != ''">
|
||||
AND process_status = #{processStatus}
|
||||
</if>
|
||||
<if test="imageYn != null and imageYn != ''">
|
||||
AND image_yn = #{imageYn}
|
||||
</if>
|
||||
<if test="corruptedYn != null and corruptedYn != ''">
|
||||
AND corrupted_yn = #{corruptedYn}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 상세 로그 목록 조회 -->
|
||||
<select id="selectZipFileDetailLogList" parameterType="ZipFileDetailLogVO" resultType="ZipFileDetailLogVO">
|
||||
SELECT
|
||||
detail_log_id,
|
||||
log_id,
|
||||
file_nm,
|
||||
file_path,
|
||||
file_size,
|
||||
file_type,
|
||||
image_yn,
|
||||
corrupted_yn,
|
||||
process_status,
|
||||
error_message,
|
||||
process_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
FROM tb_batch_zip_file_detail_log
|
||||
WHERE 1=1
|
||||
<if test="logId != null and logId != ''">
|
||||
AND log_id = #{logId}
|
||||
</if>
|
||||
<if test="fileNm != null and fileNm != ''">
|
||||
AND file_nm LIKE CONCAT('%', #{fileNm}, '%')
|
||||
</if>
|
||||
<if test="processStatus != null and processStatus != ''">
|
||||
AND process_status = #{processStatus}
|
||||
</if>
|
||||
<if test="imageYn != null and imageYn != ''">
|
||||
AND image_yn = #{imageYn}
|
||||
</if>
|
||||
<if test="corruptedYn != null and corruptedYn != ''">
|
||||
AND corrupted_yn = #{corruptedYn}
|
||||
</if>
|
||||
ORDER BY process_dttm ASC
|
||||
<if test="pagingYn == 'Y'">
|
||||
LIMIT #{startIndex}, #{recordCountPerPage}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -1,186 +0,0 @@
|
||||
<?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="go.kr.project.batch.mapper.ZipFileProcessLogMapper">
|
||||
|
||||
<!-- ZIP 파일 처리 로그 ID 생성 -->
|
||||
<select id="generateZipFileProcessLogId" resultType="String">
|
||||
SELECT CONCAT('ZPFL', LPAD(NEXTVAL(seq_batch_zip_file_process_log_id), 16, '0'))
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 등록 -->
|
||||
<insert id="insertZipFileProcessLog" parameterType="ZipFileProcessLogVO">
|
||||
INSERT INTO tb_batch_zip_file_process_log (
|
||||
log_id,
|
||||
zip_file_nm,
|
||||
zip_file_path,
|
||||
extract_path,
|
||||
archive_path,
|
||||
total_file_cnt,
|
||||
success_file_cnt,
|
||||
error_file_cnt,
|
||||
image_file_cnt,
|
||||
non_image_file_cnt,
|
||||
corrupted_file_cnt,
|
||||
process_status,
|
||||
error_message,
|
||||
start_dttm,
|
||||
end_dttm,
|
||||
REG_DTTM,
|
||||
RGTR,
|
||||
MDFCN_DTTM,
|
||||
MDFR
|
||||
) VALUES (
|
||||
#{logId},
|
||||
#{zipFileNm},
|
||||
#{zipFilePath},
|
||||
#{extractPath},
|
||||
#{archivePath},
|
||||
#{totalFileCnt},
|
||||
#{successFileCnt},
|
||||
#{errorFileCnt},
|
||||
#{imageFileCnt},
|
||||
#{nonImageFileCnt},
|
||||
#{corruptedFileCnt},
|
||||
#{processStatus},
|
||||
#{errorMessage},
|
||||
#{startDttm},
|
||||
#{endDttm},
|
||||
NOW(),
|
||||
#{rgtr},
|
||||
NOW(),
|
||||
#{mdfr}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 수정 -->
|
||||
<update id="updateZipFileProcessLog" parameterType="ZipFileProcessLogVO">
|
||||
UPDATE tb_batch_zip_file_process_log
|
||||
SET
|
||||
extract_path = #{extractPath},
|
||||
archive_path = #{archivePath},
|
||||
total_file_cnt = #{totalFileCnt},
|
||||
success_file_cnt = #{successFileCnt},
|
||||
error_file_cnt = #{errorFileCnt},
|
||||
image_file_cnt = #{imageFileCnt},
|
||||
non_image_file_cnt = #{nonImageFileCnt},
|
||||
corrupted_file_cnt = #{corruptedFileCnt},
|
||||
process_status = #{processStatus},
|
||||
error_message = #{errorMessage},
|
||||
end_dttm = #{endDttm},
|
||||
MDFCN_DTTM = NOW(),
|
||||
MDFR = #{mdfr}
|
||||
WHERE log_id = #{logId}
|
||||
</update>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 삭제 -->
|
||||
<delete id="deleteZipFileProcessLog" parameterType="String">
|
||||
DELETE FROM tb_batch_zip_file_process_log
|
||||
WHERE log_id = #{logId}
|
||||
</delete>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 조회 -->
|
||||
<select id="selectZipFileProcessLog" parameterType="String" resultType="ZipFileProcessLogVO">
|
||||
SELECT
|
||||
log_id AS logId,
|
||||
zip_file_nm AS zipFileNm,
|
||||
zip_file_path AS zipFilePath,
|
||||
extract_path AS extractPath,
|
||||
archive_path AS archivePath,
|
||||
total_file_cnt AS totalFileCnt,
|
||||
success_file_cnt AS successFileCnt,
|
||||
error_file_cnt AS errorFileCnt,
|
||||
image_file_cnt AS imageFileCnt,
|
||||
non_image_file_cnt AS nonImageFileCnt,
|
||||
corrupted_file_cnt AS corruptedFileCnt,
|
||||
process_status AS processStatus,
|
||||
error_message AS errorMessage,
|
||||
start_dttm AS startDttm,
|
||||
end_dttm AS endDttm,
|
||||
REG_DTTM AS regDttm,
|
||||
RGTR AS rgtr,
|
||||
MDFCN_DTTM AS mdfcnDttm,
|
||||
MDFR AS mdfr
|
||||
FROM tb_batch_zip_file_process_log
|
||||
WHERE log_id = #{logId}
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 목록 총 개수 조회 -->
|
||||
<select id="selectZipFileProcessLogListTotalCount" parameterType="ZipFileProcessLogVO" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM tb_batch_zip_file_process_log
|
||||
WHERE 1=1
|
||||
<if test="zipFileNm != null and zipFileNm != ''">
|
||||
AND zip_file_nm LIKE CONCAT('%', #{zipFileNm}, '%')
|
||||
</if>
|
||||
<if test="processStatus != null and processStatus != ''">
|
||||
AND process_status = #{processStatus}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- ZIP 파일 처리 로그 목록 조회 -->
|
||||
<select id="selectZipFileProcessLogList" parameterType="ZipFileProcessLogVO" resultType="ZipFileProcessLogVO">
|
||||
SELECT
|
||||
log_id AS logId,
|
||||
zip_file_nm AS zipFileNm,
|
||||
zip_file_path AS zipFilePath,
|
||||
extract_path AS extractPath,
|
||||
archive_path AS archivePath,
|
||||
total_file_cnt AS totalFileCnt,
|
||||
success_file_cnt AS successFileCnt,
|
||||
error_file_cnt AS errorFileCnt,
|
||||
image_file_cnt AS imageFileCnt,
|
||||
non_image_file_cnt AS nonImageFileCnt,
|
||||
corrupted_file_cnt AS corruptedFileCnt,
|
||||
process_status AS processStatus,
|
||||
error_message AS errorMessage,
|
||||
start_dttm AS startDttm,
|
||||
end_dttm AS endDttm,
|
||||
REG_DTTM AS regDttm,
|
||||
RGTR AS rgtr,
|
||||
MDFCN_DTTM AS mdfcnDttm,
|
||||
MDFR AS mdfr
|
||||
FROM tb_batch_zip_file_process_log
|
||||
WHERE 1=1
|
||||
<if test="zipFileNm != null and zipFileNm != ''">
|
||||
AND zip_file_nm LIKE CONCAT('%', #{zipFileNm}, '%')
|
||||
</if>
|
||||
<if test="processStatus != null and processStatus != ''">
|
||||
AND process_status = #{processStatus}
|
||||
</if>
|
||||
ORDER BY start_dttm DESC
|
||||
<if test="pagingYn == 'Y'">
|
||||
LIMIT #{startIndex}, #{recordCountPerPage}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 처리 중인 ZIP 파일 로그 조회 -->
|
||||
<select id="selectProcessingZipFileLog" parameterType="String" resultType="ZipFileProcessLogVO">
|
||||
SELECT
|
||||
log_id AS logId,
|
||||
zip_file_nm AS zipFileNm,
|
||||
zip_file_path AS zipFilePath,
|
||||
extract_path AS extractPath,
|
||||
archive_path AS archivePath,
|
||||
total_file_cnt AS totalFileCnt,
|
||||
success_file_cnt AS successFileCnt,
|
||||
error_file_cnt AS errorFileCnt,
|
||||
image_file_cnt AS imageFileCnt,
|
||||
non_image_file_cnt AS nonImageFileCnt,
|
||||
corrupted_file_cnt AS corruptedFileCnt,
|
||||
process_status AS processStatus,
|
||||
error_message AS errorMessage,
|
||||
start_dttm AS startDttm,
|
||||
end_dttm AS endDttm,
|
||||
REG_DTTM AS regDttm,
|
||||
RGTR AS rgtr,
|
||||
MDFCN_DTTM AS mdfcnDttm,
|
||||
MDFR AS mdfr
|
||||
FROM tb_batch_zip_file_process_log
|
||||
WHERE zip_file_nm = #{zipFileNm}
|
||||
AND process_status = 'PROCESSING'
|
||||
ORDER BY start_dttm DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue