diff --git a/src/main/java/com/eactive/apim/portal/config/PortalPropertyDuplicateChecker.java b/src/main/java/com/eactive/apim/portal/config/PortalPropertyDuplicateChecker.java new file mode 100644 index 0000000..0e3a7ae --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/config/PortalPropertyDuplicateChecker.java @@ -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 무결성 점검. + * + *
PTL_PROPERTY 는 (PROPERTY_GROUP_NAME, PROPERTY_NAME) 조합이 유일해야 하지만, 운영 정책상 + * DB에 유니크 제약을 걸지 않는다. 대신 부팅 완료 시점에 중복 키를 스캔하여 존재하면 ERROR 로그로 + * 남긴다. (Spring Data 리포지토리는 인터페이스라 초기화 훅이 없어, 리포지토리를 사용하는 startup + * 리스너로 점검한다.)
+ * + *중복은 {@code getOrCreateProperty} 최초 조회가 동시 요청으로 경합할 때 각각 INSERT되며 생길 수 + * 있다. 제약이 없으므로 중복 행은 자동 제거되지 않는다 — 로그를 보고 수동 정리해야 한다.
+ */ +@Slf4j +@Component +@RequiredArgsConstructor +public class PortalPropertyDuplicateChecker implements ApplicationListener