feat : querydsl 멀티디비 설정 추가.

master
Kurt92 3 months ago
parent 38a67b7763
commit de555ea965

@ -2,6 +2,7 @@ package com.worker.scheduler.epost.repository;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.worker.domain.entity.CpSetinfo;
import com.worker.scheduler.epost.dto.EPostDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -9,7 +10,9 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import javax.sql.DataSource;
import java.util.List;
import java.util.Set;
import static com.worker.domain.entity.QCpGojiPrt.cpGojiPrt;
import static com.worker.domain.entity.QEpostDelivResult.epostDelivResult;
@ -20,45 +23,34 @@ import static com.worker.domain.entity.QEpostSenderReg.epostSenderReg;
@Slf4j
@Repository
@RequiredArgsConstructor
//@RequiredArgsConstructor
public class EPostQueryDslRepository {
private final @Qualifier("cpQueryFactory") JPAQueryFactory cpQueryFactory;
private final @Qualifier("epQueryFactory") JPAQueryFactory epQueryFactory;
private final @Qualifier("cpDataSource") javax.sql.DataSource cpDs;
private final @Qualifier("epDataSource") javax.sql.DataSource epDs;
public void logWhichDb() throws Exception {
try (var c = cpDs.getConnection()) {
log.info("CP URL = {}", c.getMetaData().getURL());
log.info("CP Catalog={}, Schema={}", c.getCatalog(), c.getSchema());
}
try (var c = epDs.getConnection()) {
log.info("EP URL = {}", c.getMetaData().getURL());
log.info("EP Catalog={}, Schema={}", c.getCatalog(), c.getSchema());
}
}
@Transactional(readOnly = true, transactionManager = "epTransactionManager")
public List<EPostDto.SearchDelivTarget> findDelivResult(List<EPostDto.Deliv> dtos) {
// @Transactional(readOnly = true, transactionManager = "cpTransactionManager")
public List<EPostDto.SearchDelivTarget> findDelivResult(JPAQueryFactory queryFactory ,List<EPostDto.Deliv> dtos, Set<String> cpDeptCode) {
try {
logWhichDb();
} catch (Exception e) {
throw new RuntimeException(e);
}
// List<String> conKeys = dtos.stream()
// .map(EPostDto.Deliv::getConKey)
// .toList();
List<String> conKeys = dtos.stream()
.map(EPostDto.Deliv::getConKey)
.filter(java.util.Objects::nonNull)
.map(String::trim)
.filter(s -> !s.isEmpty())
.filter(k -> {
String[] parts = k.split("-", 3);
return parts.length == 3 && cpDeptCode.stream().anyMatch(parts[1]::startsWith);
})
.distinct()
.toList();
List<String> reginos = dtos.stream()
.map(EPostDto.Deliv::getRegiNo)
.toList();
return epQueryFactory
return queryFactory
.select(
Projections.fields(
EPostDto.SearchDelivTarget.class,
@ -88,6 +80,7 @@ public class EPostQueryDslRepository {
}
public List<EPostDto.Prt> findMakeResult(List<EPostDto.Prt> dtos) {
return null;
}
@ -98,13 +91,13 @@ public class EPostQueryDslRepository {
}
public void updateDelivResult(EPostDto.Deliv dto) {
epQueryFactory
.update(epostDelivResult)
.set(epostDelivResult.delivRsltCd, dto.getDelivrsltcd())
.where(
epostDelivResult.conKey.eq(dto.getConKey())
)
.execute();
// epQueryFactory
// .update(epostDelivResult)
// .set(epostDelivResult.delivRsltCd, dto.getDelivrsltcd())
// .where(
// epostDelivResult.conKey.eq(dto.getConKey())
// )
// .execute();
}
public void updateMakeResult(List<EPostDto.Deliv> dtos) {

@ -2,6 +2,7 @@ package com.worker.scheduler.epost.schedule;
import com.worker.scheduler.epost.dto.EPostDto;
import com.worker.scheduler.epost.service.EPostService;
import com.worker.scheduler.epost.service.EpostSetinfoService;
import com.worker.scheduler.smg.dto.SinmungoDto;
import com.worker.util.fileReader.FileParserInterface;
import com.worker.util.fileReader.FileReader;
@ -19,6 +20,8 @@ import java.util.List;
@ConditionalOnProperty(name = "scheduler.epost.enabled", havingValue = "true")
public class EPostScheduler {
private final EpostSetinfoService epostSetinfoService;
private final EPostService ePostService;
private final FileReader fileReader;
@ -32,7 +35,7 @@ public class EPostScheduler {
// esb경로 info
EPostDto.SetInfo setInfo = ePostService.findSetInfo();
EPostDto.SetInfo setInfo = epostSetinfoService.findSetInfo();
@ -55,7 +58,7 @@ public class EPostScheduler {
public void ePostRcvScheduler() {
// esb경로 info
EPostDto.SetInfo setInfo = ePostService.findSetInfo();
EPostDto.SetInfo setInfo = epostSetinfoService.findSetInfo();
String filePath = null;
if(!setInfo.getCpSetinfo().getStrValue4().equals("")) filePath = setInfo.getCpSetinfo().getStrValue4();
@ -69,7 +72,7 @@ public class EPostScheduler {
// 결과 db 폴링
// 결과종류 - 접수(recv), 제작(prt), 배달(deliv)
ePostService.saveEpostResult(parseResult);
ePostService.saveEpostResult(parseResult, setInfo);
}

@ -1,5 +1,8 @@
package com.worker.scheduler.epost.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.worker.domain.entity.CpSetinfo;
import com.worker.domain.entity.CpSetinfoId;
import com.worker.domain.entity.EpostDelivResult;
@ -13,11 +16,13 @@ import com.worker.scheduler.epost.dto.EPostDto;
import com.worker.scheduler.epost.repository.EPostQueryDslRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@ -25,6 +30,7 @@ import java.util.List;
public class EPostService {
private final Environment env;
private final ObjectMapper objectMapper;
private final CpSetinfoRepository cpSetinfoRepository;
private final EpSetinfoRepository epSetinfoRepository;
@ -32,64 +38,17 @@ public class EPostService {
private final EpEpostRceptResultRepository epEpostRceptResultRepository;
private final CpEpostDelivResultRepository cpEpostDelivResultRepository;
private final EpEpostDelivResultRepository epEpostDelivResultRepository;
private final EPostQueryDslRepository ePostQueryDslRepository;
// RequiredArgsConstructor 퀄리파이어설정을 가져가지 않아서 쿼리팩토리는 autowired로 필드 주입
@Autowired
@Qualifier("cpQueryFactory")
private JPAQueryFactory cpQueryFactory;
private final EPostQueryDslRepository ePostQueryDslRepository;
@Autowired
@Qualifier("epQueryFactory")
private JPAQueryFactory epQueryFactory;
public EPostDto.SetInfo findSetInfo() {
// 필요한 값들
// 우편기본 = INFO_1
// 문서 정보 = docCode
// 서버 이미지 경로 정보 = IMAGE
// 시군구 가능 여부 SG_ENABLE
// 전자고지 정보여부 '전자고지'
CpSetinfo cpEpostInfo = cpSetinfoRepository.findById(
CpSetinfoId.builder()
.codeName(env.getProperty("e-post.info.cp.codeName"))
.groupCode(env.getProperty("e-post.info.cp.groupCode"))
.detailCode(env.getProperty("e-post.info.cp.detailCode"))
.build()
).orElse(null);
CpSetinfo epEpostInfo = epSetinfoRepository.findById(
CpSetinfoId.builder()
.codeName(env.getProperty("e-post.info.ep.codeName"))
.groupCode(env.getProperty("e-post.info.ep.groupCode"))
.detailCode(env.getProperty("e-post.info.ep.detailCode"))
.build()
).orElse(null);
CpSetinfo cpEpostDocInfo = cpSetinfoRepository.findById(
CpSetinfoId.builder()
.codeName(env.getProperty("e-post.docCode.cp.codeName"))
.groupCode(env.getProperty("e-post.docCode.cp.groupCode"))
.detailCode(env.getProperty("e-post.docCode.cp.detailCode"))
.build()
).orElse(null);
CpSetinfo epEpostDocInfo = epSetinfoRepository.findById(
CpSetinfoId.builder()
.codeName(env.getProperty("e-post.docCode.ep.codeName"))
.groupCode(env.getProperty("e-post.docCode.ep.groupCode"))
.detailCode(env.getProperty("e-post.docCode.ep.detailCode"))
.build()
).orElse(null);
return EPostDto.SetInfo.builder()
.cpSetinfo(cpEpostInfo)
.cpEPostInfo(
buildEPostInfo(cpEpostInfo, cpEpostDocInfo)
)
.epSetinfo(epEpostInfo)
.epEPostInfo(
buildEPostInfo(epEpostInfo, epEpostDocInfo)
)
.build();
}
public void findEPostSendTarget() {
@ -98,35 +57,49 @@ public class EPostService {
}
public void saveEpostResult(List<EPostDto.EPostFileRead> parseResult) {
public void saveEpostResult(List<EPostDto.EPostFileRead> parseResult, EPostDto.SetInfo setInfo) {
// 파싱 리절트 cp ep 분리해서 넣기
// rcept , make , deliv 세개가 있음.
// 다 같은 폴더로 불규칙하게 들어오니까 일단 파싱 리절트안에 전부 해당키로 나눠서 담아놨음.
// parseResult가 리스트니까 하나씩 돌면서 키값에 맞는 매서드 호출
List<EPostDto.SearchDelivTarget> delivs = new ArrayList<>();
List<EPostDto.Prt> prts = new ArrayList<>();
List<EPostDto.Recv> recvs = new ArrayList<>();
Set<String> cpDeptCode = parseDeptCode(setInfo, "cp");
Set<String> epDeptCode = parseDeptCode(setInfo, "ep");
List<EPostDto.SearchDelivTarget> cpDelivs = new ArrayList<>();
List<EPostDto.SearchDelivTarget> epDelivs = new ArrayList<>();
List<EPostDto.Prt> cpPrts = new ArrayList<>();
List<EPostDto.Prt> epPrts = new ArrayList<>();
List<EPostDto.Recv> cpRecvs = new ArrayList<>();
List<EPostDto.Recv> epRecvs = new ArrayList<>();
parseResult.forEach(e -> {
switch(e.getKind()) {
case "deliv" -> delivs.addAll(ePostQueryDslRepository.findDelivResult(e.getResult()));
// case "rcept" ->
// case "make" ->
case "deliv" -> {
if(setInfo.getCpSetinfo() != null)
cpDelivs.addAll(ePostQueryDslRepository.findDelivResult(cpQueryFactory, e.getResult(), cpDeptCode));
if(setInfo.getEpSetinfo() != null)
epDelivs.addAll(ePostQueryDslRepository.findDelivResult(epQueryFactory, e.getResult(), epDeptCode));
}
case "rcept" -> {
}
case "make" -> {
}
}
});
log.info(delivs.toString());
log.info(prts.toString());
log.info(recvs.toString());
log.info(cpDelivs.toString());
log.info(epDelivs.toString());
// log.info(prts.toString());
// log.info(recvs.toString());
// if (delivs != null && !delivs.isEmpty()) insertDelivResults(delivs);
if (prts != null && !prts.isEmpty()) insertPrtResults(prts);
if (recvs != null && !recvs.isEmpty()) insertRecvResults(recvs);
// if (prts != null && !prts.isEmpty()) insertPrtResults(prts);
// if (recvs != null && !recvs.isEmpty()) insertRecvResults(recvs);
@ -156,26 +129,32 @@ public class EPostService {
private void insertRecvResults(List<EPostDto.Recv> recvs) {}
private EPostDto.EPostInfo buildEPostInfo(CpSetinfo ePostInfo, CpSetinfo ePostDocInfo) {
if(ePostInfo == null) return null;
return EPostDto.EPostInfo.builder()
.conOrg(ePostDocInfo.getStrValue1())
.rceptId(ePostDocInfo.getStrValue2())
.apvlNb(ePostDocInfo.getStrValue3())
.filePath(ePostDocInfo.getStrValue4())
.postId(ePostDocInfo.getStrValue5())
.addPath(ePostDocInfo.getStrValue6())
.docCodes(findDocCodes(ePostDocInfo))
.build();
}
//ePost docCode 리스트화
private List<String> findDocCodes(CpSetinfo ePostDocInfo) {
return List.of(ePostDocInfo.getStrValue1(),
ePostDocInfo.getStrValue2(),
ePostDocInfo.getStrValue3(),
ePostDocInfo.getStrValue4(),
ePostDocInfo.getStrValue5());
private Set<String> parseDeptCode(EPostDto.SetInfo setInfo, String kind) {
String json = null;
if(kind.equals("cp") && setInfo.getCpSetinfo() != null)
json = setInfo.getCpSetinfo().getStrValue6();
if(kind.equals("ep") && setInfo.getEpSetinfo() != null)
json = setInfo.getEpSetinfo().getStrValue6();
if (json == null || json.isBlank()) {
return Collections.emptySet();
}
try {
Map<String, List<Integer>> map = objectMapper.readValue(
json,
new TypeReference<Map<String, List<Integer>>>() {}
);
return map.values().stream()
.filter(list -> list != null && list.size() > 1 && list.get(1) != null)
.map(list -> list.get(1)) // 2번째 값
.map(String::valueOf) // 문자열로 통일
.collect(Collectors.toUnmodifiableSet());
} catch (Exception e) {
return Collections.emptySet();
}
}

@ -0,0 +1,161 @@
package com.worker.scheduler.epost.service;
import com.worker.domain.entity.CpSetinfo;
import com.worker.domain.entity.CpSetinfoId;
import com.worker.domain.repo.cp.CpBdongRepository;
import com.worker.domain.repo.cp.CpSetinfoRepository;
import com.worker.domain.repo.ep.EpBdongRepository;
import com.worker.domain.repo.ep.EpSetinfoRepository;
import com.worker.scheduler.epost.dto.EPostDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
@RequiredArgsConstructor
@Slf4j
public class EpostSetinfoService {
private final Environment env;
private final CpSetinfoRepository cpSetinfoRepository;
private final EpSetinfoRepository epSetinfoRepository;
// DataSources (가용성 체크용)
@Qualifier("cpDataSource")
private final DataSource cpDataSource;
@Qualifier("epDataSource")
private final DataSource epDataSource;
public EPostDto.SetInfo findSetInfo() {
CpSetinfoId cpInfoId = CpSetinfoId.builder()
.codeName(env.getProperty("e-post.info.cp.codeName"))
.groupCode(env.getProperty("e-post.info.cp.groupCode"))
.detailCode(env.getProperty("e-post.info.cp.detailCode"))
.build();
CpSetinfoId epInfoId = CpSetinfoId.builder()
.codeName(env.getProperty("e-post.info.ep.codeName"))
.groupCode(env.getProperty("e-post.info.ep.groupCode"))
.detailCode(env.getProperty("e-post.info.ep.detailCode"))
.build();
CpSetinfoId cpDocId = CpSetinfoId.builder()
.codeName(env.getProperty("e-post.docCode.cp.codeName"))
.groupCode(env.getProperty("e-post.docCode.cp.groupCode"))
.detailCode(env.getProperty("e-post.docCode.cp.detailCode"))
.build();
CpSetinfoId epDocId = CpSetinfoId.builder()
.codeName(env.getProperty("e-post.docCode.ep.codeName"))
.groupCode(env.getProperty("e-post.docCode.ep.groupCode"))
.detailCode(env.getProperty("e-post.docCode.ep.detailCode"))
.build();
// ----- CP -----
CpSetinfo cpEpostInfo = null;
CpSetinfo cpEpostDocInfo = null;
EPostDto.EPostInfo cpEPostInfo = null;
if (isDsAvailable(cpDataSource)) {
try {
cpEpostInfo = cpSetinfoRepository.findById(cpInfoId).orElse(null);
cpEpostDocInfo = cpSetinfoRepository.findById(cpDocId).orElse(null);
cpEPostInfo = buildEPostInfo(cpEpostInfo, cpEpostDocInfo);
} catch (Exception e) {
log.warn("[CP] 조회/빌드 실패. CP스킵: {}", e.getMessage());
}
} else {
log.info("[CP] DB 비가용. CP 스킵.");
}
// ----- EP -----
CpSetinfo epEpostInfo = null;
CpSetinfo epEpostDocInfo = null;
EPostDto.EPostInfo epEPostInfo = null;
if (isDsAvailable(epDataSource)) {
try {
epEpostInfo = epSetinfoRepository.findById(epInfoId).orElse(null);
epEpostDocInfo = epSetinfoRepository.findById(epDocId).orElse(null);
epEPostInfo = buildEPostInfo(epEpostInfo, epEpostDocInfo);
} catch (Exception e) {
log.warn("[EP] 조회/빌드 실패. EP 스킵: {}", e.getMessage());
}
} else {
log.info("[EP] DB 비가용. EP 조회 스킵");
}
// ----- 결과 -----
return EPostDto.SetInfo.builder()
.cpSetinfo(cpEpostInfo) // null 허용
.cpEPostInfo(cpEPostInfo) // null 허용
.epSetinfo(epEpostInfo) // null 허용
.epEPostInfo(epEPostInfo) // null 허용
.build();
}
/** DataSource 가용성 체크: 커넥션 시도만 해보고 실패하면 비가용 */
private boolean isDsAvailable(DataSource ds) {
if (ds == null) return false;
try (Connection c = ds.getConnection()) {
return true;
} catch (Exception e) {
return false;
}
}
/** null-safe EPostInfo 빌드: 입력 둘 중 하나라도 없으면 null 반환 */
private EPostDto.EPostInfo buildEPostInfo(CpSetinfo ePostInfo, CpSetinfo ePostDocInfo) {
if (ePostInfo == null || ePostDocInfo == null) {
return null;
}
return EPostDto.EPostInfo.builder()
.conOrg(trimOrNull(ePostDocInfo.getStrValue1()))
.rceptId(trimOrNull(ePostDocInfo.getStrValue2()))
.apvlNb(trimOrNull(ePostDocInfo.getStrValue3()))
.filePath(trimOrNull(ePostDocInfo.getStrValue4()))
.postId(trimOrNull(ePostDocInfo.getStrValue5()))
.addPath(trimOrNull(ePostDocInfo.getStrValue6()))
.docCodes(findDocCodes(ePostDocInfo))
.build();
}
/** 문서코드 리스트: null/공백 제거 + trim + 중복 제거 + 불변화 */
private List<String> findDocCodes(CpSetinfo ePostDocInfo) {
if (ePostDocInfo == null) {
return Collections.emptyList();
}
List<String> codes = Stream.of(
ePostDocInfo.getStrValue1(),
ePostDocInfo.getStrValue2(),
ePostDocInfo.getStrValue3(),
ePostDocInfo.getStrValue4(),
ePostDocInfo.getStrValue5()
)
.filter(Objects::nonNull)
.map(String::trim)
.filter(s -> !s.isEmpty())
.distinct()
.collect(Collectors.toList());
return Collections.unmodifiableList(codes);
}
private String trimOrNull(String s) {
if (s == null) return null;
String t = s.trim();
return t.isEmpty() ? null : t;
}
}

@ -11,6 +11,8 @@ import com.worker.util.common.commEnum.StateEnum;
import com.worker.util.xmlFileMaker.XmlMacker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.io.IOException;
@ -24,16 +26,21 @@ import java.util.concurrent.ThreadLocalRandom;
public class XmlSend {
private final XmlMacker xmlMacker;
private final JPAQueryFactory cpQueryFactory;
private final JPAQueryFactory epQueryFactory;
private final CpUserRepository cpUserRepository;
private final EpUserRepository epUserRepository;
private final XmlSendQueryDslRepository xmlSendQueryDslRepository;
private final CpAnswerRepository cpAnswerRepository;
private final EpAnswerRepository epAnswerRepository;
// RequiredArgsConstructor 퀄리파이어설정을 가져가지 않아서 쿼리팩토리는 autowired로 필드 주입
@Autowired
@Qualifier("cpQueryFactory")
private JPAQueryFactory cpQueryFactory;
@Autowired
@Qualifier("epQueryFactory")
private JPAQueryFactory epQueryFactory;
// 실행 대상 답변 찾기
public SinmungoDto.Send.Answers findAnswersByStatus(String status) {

@ -43,9 +43,9 @@ spring:
scheduler:
smg:
enabled: true
epost:
enabled: false
epost:
enabled: true
tax-sunap:
enabled: false
update:
@ -74,20 +74,20 @@ e-post:
cp:
codeName: EPOST_INFO
groupCode: INFO_1
detailCode: DEV
detailCode: LOCAL
ep:
codeName: EPOST_INFO
groupCode: INFO_1
detailCode: DEV
detailCode: LOCAL
docCode:
cp:
codeName: EPOST_INFO
groupCode: DOC_CODE
detailCode: DEV
detailCode: LOCAL
ep:
codeName: EPOST_INFO
groupCode: DOC_CODE
detailCode: DEV
detailCode: LOCAL

Loading…
Cancel
Save