주식당 총 15개의 데이터가 넘어온다. 두 개를 일자을 기준으로 변하는 것과 변하지 않는것으로 분류하였다.
@Getter
@Setter
@Entity
public class StockInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 종목코드
@Column(unique = true)
private String itmsNm;
// 시장구분
private String mrktCtg;
// 종목명
private String srtnCd;
// 고유번호
private String isinCd;
}
중복저장을 방지하기 위해서 itmsNm에 unique 속성을 부여하였다.
public interface StockInfoRepository extends JpaRepository<StockInfo, Long> {
StockInfo findByItmsNm(String itmsNm);
StockInfo findBySrtnCd(String srtnCd);
}
@Service
public class StockInfoService {
private final StockInfoRepository stockInfoRepository;
public StockInfoService(StockInfoRepository stockInfoRepository) {
this.stockInfoRepository = stockInfoRepository;
}
public StockInfo save(StockInfo stockInfo) {
if(stockInfoRepository.findByItmsNm(stockInfo.getItmsNm()) == null) {
return stockInfoRepository.save(stockInfo);
}
return null;
}
public StockInfo findByItmsNm(String itmsNm) {
return stockInfoRepository.findByItmsNm(itmsNm);
}
public StockInfo findBySrtnCd(String srtnCd) {
return stockInfoRepository.findBySrtnCd(srtnCd);
}
}
save를 하면 unique인 itmsNm에 따라서 중복이 방지되는데 테스트 결과 ID 값이 중복 저장을 시도할때 증가하는 경우가 발생하였다. 그래서, DB에 해당 정보가 있는지 확인한 후 저장하는 방식을 선택하였는데 사실 좋은 방법인지 모르겠다.. 좀 더 찾아봐야할거 같다.
@SpringBootTest
public class StockInfoTest {
@Autowired
private StockInfoRepository stockInfoRepository;
@Test
void testStockInfoSaveJpa() {
StockInfo s1 = new StockInfo();
s1.setItmsNm("900110");
s1.setMrktCtg("KOSDAQ");
s1.setSrtnCd("이스트아시아홀딩스");
s1.setIsinCd("HK0000057197");
if(stockInfoRepository.findByItmsNm(s1.getItmsNm()) == null) {
assertThat(s1).isEqualTo(this.stockInfoRepository.save(s1));
}
StockInfo s2 = new StockInfo();
s2.setItmsNm("900110");
s2.setMrktCtg("KOSDAQ");
s2.setSrtnCd("이스트아시아홀딩스");
s2.setIsinCd("HK0000057197");
if(stockInfoRepository.findByItmsNm(s2.getItmsNm()) == null) {
assertThat(s2).isEqualTo(this.stockInfoRepository.save(s2));
}
StockInfo s3 = new StockInfo();
s3.setItmsNm("900270");
s3.setMrktCtg("KOSDAQ");
s3.setSrtnCd("헝셩그룹");
s3.setIsinCd("HK0000214814");
if(stockInfoRepository.findByItmsNm(s3.getItmsNm()) == null) {
assertThat(s3).isEqualTo(this.stockInfoRepository.save(s3));
}
assertEquals("1", "1");
}
@Test
void testStockInfoFindAllJpa() {
List<StockInfo> all = this.stockInfoRepository.findAll();
assertEquals(all.size(), 2);
StockInfo s = all.get(0);
assertEquals("900110", s.getItmsNm());
}
@Test
void testStockInfoFindItmsNmJpa() {
StockInfo s = this.stockInfoRepository.findByItmsNm("900110");
assertEquals("이스트아시아홀딩스", s.getSrtnCd());
}
@Test
void testStockInfoFindSrtnCdJpa() {
StockInfo s = this.stockInfoRepository.findBySrtnCd("이스트아시아홀딩스");
assertEquals("900110", s.getItmsNm());
}
}
해당 4가지 테스트 케이스를 모두 통과하였다.
@Entity
@Getter
@Setter
public class StockPrice {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 종목코드
private String itmsNm;
// 시가
private Long mkp;
// 종가
private Long clpr;
// 고가
private Long hipr;
// 저가
private Long lopr;
// 거래량
private Long trqu;
// 거래대금
private Long trPrc;
// 시가총액
private Long mkrtTotAmt;
// 기준일자
private LocalDate basDt;
}
LocalDateTime의 경우 뒤에 시간이 붙는다. 해당 Entity에 시간을 필요없어서 LocalDate의 형식으로 지정하였다.
public interface StockPriceRepository extends JpaRepository<StockPrice, Long> {
List<StockPrice> findByItmsNm(String itmsNm);
List<StockPrice> findByBasDt(LocalDate basDt);
List<StockPrice> findByItmsNmAndBasDtBetween(String itmsNm, LocalDate startDate, LocalDate endDate);
}
일단은 종목코드, 기준날짜, 종목코드 및 기간으로 조회하는 기능을 추가하였다.
@Service
public class StockPriceService {
private final StockPriceRepository stockPriceRepository;
public StockPriceService(StockPriceRepository stockPriceRepository) {
this.stockPriceRepository = stockPriceRepository;
}
public StockPrice save(StockPrice stockPrice) {
return stockPriceRepository.save(stockPrice);
}
public List<StockPrice> findByItmsNm(String itmsNm) {
return stockPriceRepository.findByItmsNm(itmsNm);
}
public List<StockPrice> findByBasDt(LocalDate basDt) {
return stockPriceRepository.findByBasDt(basDt);
}
public List<StockPrice> findByItmsNmAndBasDtBetween(String itmsNm, LocalDate startDate, LocalDate endDate) {
return stockPriceRepository.findByItmsNmAndBasDtBetween(itmsNm, startDate, endDate);
}
}
해당 부분을 테스트하면서 테스트는 클래스를 만든 순서가 아닌 클래스 이름을 기준으로 실행한다는 것을 배울 수 있었다. 데이터를 추가하는 함수를 가장 먼저 시행하도록 @Order 어노테이션을 사용하였다.
@SpringBootTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class StockPriceTest {
@Autowired
private StockPriceRepository stockPriceRepository;
@Test
@Order(1)
public void testSaveStockPrice() {
StockPrice stockPrice1 = createSampleStockPrice("ABC", LocalDate.of(2023, 12, 1), 1000L, 1200L, 900L, 800L, 15000L, 300000L, 5000000L);
StockPrice stockPrice2 = createSampleStockPrice("ABC", LocalDate.of(2023, 12, 2), 1500L, 1300L, 1100L, 1000L, 18000L, 400000L, 6000000L);
StockPrice stockPrice3 = createSampleStockPrice("ABC", LocalDate.of(2023, 12, 3), 2000L, 1800L, 1500L, 1400L, 20000L, 450000L, 7000000L);
StockPrice stockPrice4 = createSampleStockPrice("GHI", LocalDate.of(2023, 12, 4), 2500L, 2200L, 1900L, 1800L, 22000L, 500000L, 7500000L);
StockPrice stockPrice5 = createSampleStockPrice("JKL", LocalDate.of(2023, 12, 1), 3000L, 2700L, 2300L, 2200L, 25000L, 550000L, 8000000L);
assertThat(stockPrice1).isEqualTo(this.stockPriceRepository.save(stockPrice1));
assertThat(stockPrice2).isEqualTo(this.stockPriceRepository.save(stockPrice2));
assertThat(stockPrice3).isEqualTo(this.stockPriceRepository.save(stockPrice3));
assertThat(stockPrice4).isEqualTo(this.stockPriceRepository.save(stockPrice4));
assertThat(stockPrice5).isEqualTo(this.stockPriceRepository.save(stockPrice5));
}
@Test
@Order(3)
public void testFindByItmsNm() {
String itmsNm = "ABC";
List<StockPrice> stockPrices = this.stockPriceRepository.findByItmsNm(itmsNm);
assertEquals(3, stockPrices.size());
}
@Test
@Order(2)
public void testFindByBasDt() {
LocalDate basDt = LocalDate.of(2023, 12, 1); // 날짜 설정
List<StockPrice> stockPrices = this.stockPriceRepository.findByBasDt(basDt);
assertEquals(2, stockPrices.size());
}
@Test
@Order(4)
public void testFindByItmsNmAndBasDtBetween() {
String itmsNm = "ABC"; // 종목명 설정
LocalDate startDate = LocalDate.of(2023, 11, 1); // 시작 날짜 설정
LocalDate endDate = LocalDate.of(2023, 12, 2); // 끝 날짜 설정
List<StockPrice> stockPrices = this.stockPriceRepository.findByItmsNmAndBasDtBetween(itmsNm, startDate, endDate);
assertEquals(2, stockPrices.size());
}
public static StockPrice createSampleStockPrice(String itmsNm, LocalDate basDt, Long mkp, Long clpr, Long hipr, Long lopr,
Long trqu, Long trPrc, Long mkrtTotAmt) {
StockPrice stockPrice = new StockPrice();
stockPrice.setItmsNm(itmsNm);
stockPrice.setBasDt(basDt);
stockPrice.setMkp(mkp);
stockPrice.setClpr(clpr);
stockPrice.setHipr(hipr);
stockPrice.setLopr(lopr);
stockPrice.setTrqu(trqu);
stockPrice.setTrPrc(trPrc);
stockPrice.setMkrtTotAmt(mkrtTotAmt);
return stockPrice;
}
}
다음에는 이제 데이터를 추가하여 보겠다.