@@ -62,7 +62,12 @@ public void importStocksFromJson(String jsonFilePath) {
6262 int invalidated = 0 ;
6363 int preserved = 0 ;
6464
65+ // 기존 종목들을 symbol로 조회하여 Map으로 변환 (성능 최적화)
66+ Map <String , Stock > existingStocksMap = stockRepository .findAll ().stream ()
67+ .collect (Collectors .toMap (Stock ::getSymbol , stock -> stock , (existing , replacement ) -> existing ));
68+
6569 // 1. 종목 마스터에 있는 종목 처리 (추가/업데이트)
70+ List <Stock > stocksToSave = new ArrayList <>();
6671 for (Map <String , Object > stockData : stocksData ) {
6772 try {
6873 String symbol = (String ) stockData .get ("symbol" );
@@ -86,63 +91,38 @@ public void importStocksFromJson(String jsonFilePath) {
8691 continue ;
8792 }
8893
89- // 섹터 코드 매핑 (KIS 업종 코드 → DomesticSector 또는 OverseasSector)
90- // KIS에서 제공하는 공식 업종 코드를 그대로 사용합니다.
91- if (sectorCodeStr != null && !sectorCodeStr .isEmpty () && !sectorCodeStr .equals ("nan" )) {
92- if (exchangeNum == EXCHANGENUM .KOSPI || exchangeNum == EXCHANGENUM .KOSDAQ ) {
93- // 국내 주식: DomesticSector 사용
94- DomesticSector domesticSector = DomesticSector .fromCode (sectorCodeStr , exchangeNum );
95- if (domesticSector == DomesticSector .UNKNOWN ) {
96- log .debug ("Domestic sector mapping failed: code={}, exchange={}, stock={}. Using UNKNOWN." ,
97- sectorCodeStr , exchangeNum , symbol );
98- } else {
99- log .trace ("Mapped KIS sector code: {} -> DomesticSector: {} for stock: {}" ,
100- sectorCodeStr , domesticSector , symbol );
101- }
102- } else if (exchangeNum == EXCHANGENUM .NAS || exchangeNum == EXCHANGENUM .NYS || exchangeNum == EXCHANGENUM .AMS ) {
103- // 해외 주식: OverseasSector 사용
104- OverseasSector overseasSector = OverseasSector .fromCode (sectorCodeStr );
105- if (overseasSector == OverseasSector .UNKNOWN ) {
106- log .debug ("Overseas sector mapping failed: code={}, exchange={}, stock={}. Using UNKNOWN." ,
107- sectorCodeStr , exchangeNum , symbol );
108- } else {
109- log .trace ("Mapped KIS sector code: {} -> OverseasSector: {} for stock: {}" ,
110- sectorCodeStr , overseasSector , symbol );
111- }
112- }
113- }
114-
94+ Stock stock ;
11595 // 기존 종목 확인
116- Optional <Stock > existingStock = stockRepository .findBySymbol (symbol );
117-
118- if (existingStock .isPresent ()) {
96+ if (existingStocksMap .containsKey (symbol )) {
11997 // 기존 종목 업데이트
120- Stock stock = existingStock .get ();
98+ stock = existingStocksMap .get (symbol );
12199 stock .updateSymbolNameIfNull (symbolName );
122100 // 종목 마스터에 있으므로 valid = true로 설정
123101 setStockValid (stock , true );
124- // 섹터 업데이트
125- if (sectorCodeStr != null && !sectorCodeStr .isEmpty () && !sectorCodeStr .equals ("nan" )) {
126- stock .setSectorByExchange (sectorCodeStr , exchangeNum );
127- }
128- stockRepository .save (stock );
129102 updated ++;
130103 } else {
131104 // 새 종목 생성
132- Stock stock = createStock (symbol , symbolName , securityName , exchangeNum , true );
133- // 섹터 설정
134- if (sectorCodeStr != null && !sectorCodeStr .isEmpty () && !sectorCodeStr .equals ("nan" )) {
135- stock .setSectorByExchange (sectorCodeStr , exchangeNum );
136- }
137- stockRepository .save (stock );
105+ stock = createStock (symbol , symbolName , securityName , exchangeNum , true );
138106 saved ++;
139107 }
108+
109+ // 섹터 업데이트
110+ if (sectorCodeStr != null && !sectorCodeStr .isEmpty () && !sectorCodeStr .equals ("nan" )) {
111+ stock .setSectorByExchange (sectorCodeStr , exchangeNum );
112+ }
113+
114+ stocksToSave .add (stock );
140115
141116 } catch (Exception e ) {
142117 log .error ("Error processing stock: {}" , stockData , e );
143118 skipped ++;
144119 }
145120 }
121+
122+ // 배치로 저장
123+ if (!stocksToSave .isEmpty ()) {
124+ stockRepository .saveAll (stocksToSave );
125+ }
146126
147127 // 2. 종목 마스터에 없는 종목 찾기
148128 List <Stock > allStocks = stockRepository .findAll ();
0 commit comments