Skip to content

Commit 82f5326

Browse files
authored
Merge pull request #99 from SynergyX-AI-Pattern/refactor/#98_watchlist_add_changerate_price
[REFACTOR] 관심종목 엔티티에 orm, fetch join 적용 및 필드 추가 #98
2 parents 3d90736 + b369fb6 commit 82f5326

File tree

7 files changed

+75
-38
lines changed

7 files changed

+75
-38
lines changed

src/main/java/com/synergyx/trading/dto/InterestStock/InterestStockResponseDTO.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ public class InterestStockResponseDTO {
1010
private Long stockId;
1111
private String stockName;
1212
private String stockSymbol;
13+
private String price;
14+
private String changeRate;
1315
private String imageUrl;
1416

15-
public InterestStockResponseDTO(Long stockId, String stockName, String stockSymbol, String imageUrl) {
17+
public InterestStockResponseDTO(Long stockId, String stockName, String stockSymbol, String price, String changeRate, String imageUrl) {
1618
this.stockId = stockId;
1719
this.stockName = stockName;
1820
this.stockSymbol = stockSymbol;
21+
this.price = price;
22+
this.changeRate = changeRate;
1923
this.imageUrl = imageUrl;
2024
}
2125
}

src/main/java/com/synergyx/trading/model/RecentViewStock.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ public class RecentViewStock {
1919
@GeneratedValue(strategy = GenerationType.IDENTITY)
2020
private Long id;
2121

22-
@Column(name = "user_id", nullable = false)
23-
private Long userId;
22+
@ManyToOne(fetch = FetchType.LAZY)
23+
@JoinColumn(name = "user_id", nullable = false)
24+
private User user;
2425

25-
@Column(name = "stock_id", nullable = false)
26-
private Long stockId;
26+
@ManyToOne(fetch = FetchType.LAZY)
27+
@JoinColumn(name = "stock_id", nullable = false)
28+
private Stock stock;
2729

2830
@Column(name = "viewed_at", nullable = false)
2931
private LocalDateTime viewedAt;

src/main/java/com/synergyx/trading/model/Stock.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ public class Stock extends BaseEntity {
2424

2525
@Column(name = "image_url", nullable = true, length = 255)
2626
private String imageUrl;
27+
28+
@OneToOne(mappedBy = "stock")
29+
private StockDetail stockDetail;
2730
}

src/main/java/com/synergyx/trading/repository/InterestStockRepository.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.synergyx.trading.repository;
22

33
import com.synergyx.trading.model.InterestStock;
4+
import org.springframework.data.jpa.repository.EntityGraph;
45
import org.springframework.data.jpa.repository.JpaRepository;
56
import org.springframework.stereotype.Repository;
67

@@ -11,10 +12,9 @@
1112
public interface InterestStockRepository extends JpaRepository<InterestStock, Long> {
1213
Optional<InterestStock> findByUserIdAndStockId(Long userId, Long stockId);
1314

15+
@EntityGraph(attributePaths = {"stock", "stock.stockDetail"})
1416
List<InterestStock> findAllByUserId(Long userId);
1517

16-
void deleteByUserIdAndStockId(Long userId, Long stockId);
17-
1818
boolean existsByUserIdAndStockId(Long userId, Long stockId);
1919
}
2020

src/main/java/com/synergyx/trading/repository/RecentViewStockRepository.java

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.synergyx.trading.dto.InterestStock.InterestStockResponseDTO;
44
import com.synergyx.trading.model.RecentViewStock;
5+
import org.springframework.data.jpa.repository.EntityGraph;
56
import org.springframework.data.jpa.repository.JpaRepository;
67
import org.springframework.data.jpa.repository.Modifying;
78
import org.springframework.data.jpa.repository.Query;
@@ -11,34 +12,27 @@
1112

1213
public interface RecentViewStockRepository extends JpaRepository<RecentViewStock, Long> {
1314

14-
@Query("""
15-
SELECT new com.synergyx.trading.dto.InterestStock.InterestStockResponseDTO(
16-
s.id, s.name, s.symbol, s.imageUrl
17-
)
18-
FROM RecentViewStock r
19-
JOIN Stock s ON r.stockId = s.id
20-
WHERE r.userId = :userId
21-
ORDER BY r.viewedAt DESC
22-
""")
23-
List<InterestStockResponseDTO> findRecentStocksWithInfo(@Param("userId") Long userId);
24-
15+
@EntityGraph(attributePaths = {"stock", "stock.stockDetail"})
16+
List<RecentViewStock> findByUserIdOrderByViewedAtDesc(Long userId);
2517

2618
// 중복 제거 (stockId 1개 삭제)
2719
void deleteByUserIdAndStockId(Long userId, Long stockId);
2820

2921
// 20개 초과된 데이터 삭제
3022
@Modifying
3123
@Query(value = """
32-
DELETE FROM recent_view_stock
33-
WHERE user_id = :userId
34-
AND id NOT IN (
35-
SELECT id FROM (
36-
SELECT id FROM recent_view_stock
37-
WHERE user_id = :userId
38-
ORDER BY viewed_at DESC
39-
LIMIT 20
40-
) AS tmp
41-
)
24+
DELETE r FROM recent_view_stock r
25+
WHERE r.user_id = :userId
26+
AND r.id NOT IN (
27+
SELECT id
28+
FROM (
29+
SELECT id
30+
FROM recent_view_stock
31+
WHERE user_id = :userId
32+
ORDER BY viewed_at DESC
33+
LIMIT 20
34+
) tmp
35+
)
4236
""", nativeQuery = true)
4337
void deleteOverLimit(Long userId);
4438
}

src/main/java/com/synergyx/trading/service/InterestStockService/InterestStockCommandServiceImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,22 @@ public void removeInterest(Long userId, Long stockId) {
7979
@Override
8080
@Transactional(propagation = REQUIRES_NEW)
8181
public void addRecentView(Long userId, Long stockId) {
82+
// 사용자 조회
83+
User user = userRepository.findById(userId)
84+
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
85+
86+
// 종목 조회
87+
Stock stock = stockRepository.findById(stockId)
88+
.orElseThrow(() -> new GeneralException(ErrorStatus.STOCK_NOT_FOUND));
89+
8290
// 중복 제거
8391
recentViewStockRepository.deleteByUserIdAndStockId(userId, stockId);
8492

93+
// 기록 저장
8594
recentViewStockRepository.save(
8695
RecentViewStock.builder()
87-
.userId(userId)
88-
.stockId(stockId)
96+
.user(user)
97+
.stock(stock)
8998
.viewedAt(LocalDateTime.now())
9099
.build()
91100
);

src/main/java/com/synergyx/trading/service/InterestStockService/InterestStockQueryServiceImpl.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.synergyx.trading.apiPayload.code.status.ErrorStatus;
44
import com.synergyx.trading.apiPayload.exception.GeneralException;
55
import com.synergyx.trading.dto.InterestStock.InterestStockResponseDTO;
6+
import com.synergyx.trading.model.Stock;
7+
import com.synergyx.trading.model.StockDetail;
68
import com.synergyx.trading.model.User;
79
import com.synergyx.trading.repository.InterestStockRepository;
810
import com.synergyx.trading.repository.RecentViewStockRepository;
@@ -13,6 +15,8 @@
1315

1416
import java.util.List;
1517

18+
import static com.synergyx.trading.util.ParsingUtil.toFormattedNumber;
19+
1620
@Service
1721
@RequiredArgsConstructor
1822
public class InterestStockQueryServiceImpl implements InterestStockQueryService {
@@ -34,13 +38,20 @@ public List<InterestStockResponseDTO> getInterestList(Long userId) {
3438
User user = getValidUser(userId);
3539

3640
return interestStockRepository.findAllByUserId(userId).stream()
37-
.map(i -> InterestStockResponseDTO.builder()
38-
.stockId(i.getStock().getId())
39-
.stockName(i.getStock().getName())
40-
.stockSymbol(i.getStock().getSymbol())
41-
.imageUrl(i.getStock().getImageUrl())
42-
.build()
43-
).toList();
41+
.map(i -> {
42+
Stock stock = i.getStock();
43+
StockDetail detail = stock.getStockDetail(); // entity graph로 fetch
44+
45+
return InterestStockResponseDTO.builder()
46+
.stockId(i.getStock().getId())
47+
.stockName(i.getStock().getName())
48+
.stockSymbol(i.getStock().getSymbol())
49+
.price(detail != null ? toFormattedNumber(detail.getPrice()) : null)
50+
.changeRate(detail != null ? (detail.getChangeRate() + "%") : null)
51+
.imageUrl(i.getStock().getImageUrl())
52+
.build();
53+
})
54+
.toList();
4455
}
4556

4657
/**
@@ -54,7 +65,21 @@ public List<InterestStockResponseDTO> getInterestList(Long userId) {
5465
public List<InterestStockResponseDTO> getRecentViewStocks(Long userId) {
5566
User user = getValidUser(userId);
5667

57-
return recentViewStockRepository.findRecentStocksWithInfo(userId);
68+
return recentViewStockRepository.findByUserIdOrderByViewedAtDesc(userId).stream()
69+
.map(r -> {
70+
var stock = r.getStock();
71+
var detail = stock.getStockDetail();
72+
73+
return InterestStockResponseDTO.builder()
74+
.stockId(stock.getId())
75+
.stockName(stock.getName())
76+
.stockSymbol(stock.getSymbol())
77+
.price(detail != null ? toFormattedNumber(detail.getPrice()) : null)
78+
.changeRate(detail != null ? (detail.getChangeRate() + "%") : null)
79+
.imageUrl(stock.getImageUrl())
80+
.build();
81+
})
82+
.toList();
5883
}
5984

6085
/**

0 commit comments

Comments
 (0)