PortalProperty 부팅 시 중복키 점검 기능 추가
- (PROPERTY_GROUP_NAME, PROPERTY_NAME) 유일성 검증 - 중복 발견 시 ERROR 로그 출력 및 수동 정리 안내 - JSESSIONID 쿠키 이름 변경 (PORTAL_JSESSIONID → JSESSIONID_PORTAL)
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
package com.eactive.apim.portal.config;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.portalproperty.repository.PortalPropertyRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기동 시 PTL_PROPERTY 무결성 점검.
|
||||||
|
*
|
||||||
|
* <p>PTL_PROPERTY 는 (PROPERTY_GROUP_NAME, PROPERTY_NAME) 조합이 유일해야 하지만, 운영 정책상
|
||||||
|
* DB에 유니크 제약을 걸지 않는다. 대신 부팅 완료 시점에 중복 키를 스캔하여 존재하면 ERROR 로그로
|
||||||
|
* 남긴다. (Spring Data 리포지토리는 인터페이스라 초기화 훅이 없어, 리포지토리를 사용하는 startup
|
||||||
|
* 리스너로 점검한다.)</p>
|
||||||
|
*
|
||||||
|
* <p>중복은 {@code getOrCreateProperty} 최초 조회가 동시 요청으로 경합할 때 각각 INSERT되며 생길 수
|
||||||
|
* 있다. 제약이 없으므로 중복 행은 자동 제거되지 않는다 — 로그를 보고 수동 정리해야 한다.</p>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PortalPropertyDuplicateChecker implements ApplicationListener<ApplicationReadyEvent> {
|
||||||
|
|
||||||
|
private final PortalPropertyRepository portalPropertyRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||||
|
List<Object[]> duplicates;
|
||||||
|
try {
|
||||||
|
duplicates = portalPropertyRepository.findDuplicatePropertyKeys();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[PortalProperty 무결성] 중복 점검 쿼리 실패", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duplicates == null || duplicates.isEmpty()) {
|
||||||
|
log.info("[PortalProperty 무결성] (PROPERTY_GROUP_NAME, PROPERTY_NAME) 중복 없음");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) (group, name) 은 유일해야 한다
|
||||||
|
// 2) 중복된 값 목록을 남긴다
|
||||||
|
log.error("[PortalProperty 무결성] (PROPERTY_GROUP_NAME, PROPERTY_NAME) 조합은 유일해야 합니다. "
|
||||||
|
+ "DB 유니크 제약이 없어 중복 {}건이 방치되어 있습니다. 수동 정리 필요:", duplicates.size());
|
||||||
|
for (Object[] row : duplicates) {
|
||||||
|
log.error(" - PROPERTY_GROUP_NAME='{}', PROPERTY_NAME='{}', count={}", row[0], row[1], row[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ server:
|
|||||||
session:
|
session:
|
||||||
timeout: 10m
|
timeout: 10m
|
||||||
cookie:
|
cookie:
|
||||||
name: PORTAL_JSESSIONID
|
name: JSESSIONID_PORTAL
|
||||||
encoding:
|
encoding:
|
||||||
charset: UTF-8
|
charset: UTF-8
|
||||||
port: '39130'
|
port: '39130'
|
||||||
|
|||||||
Reference in New Issue
Block a user