pakage com.metacoding.bankv1.account;
import com.metacoding.bankv1.user.User;
import lombok.Data;
import java.util.List;
public class AccountResponse {
@Data
public static class DetailDTO {
private String fullname;
private int number;
private int balance;
private List<HistoryDTO> histories;
public DetailDTO(User sessionUser, Account account, List<HistoryDTO> histories) {
this.fullname = sessionUser.getFullname();
this.number = account.getNumber();
this.balance = account.getBalance();
this.histories = histories;
}
}
// 두번째 쿼리
@Data
public static class HistoryDTO {
private String createdAt;
private int withdrawNumber;
private int depositNumber;
private int amount;
private int balance;
private String type;
}
}
public List<AccountResponse.HistoryDTO> findByAllNumber(Integer number) {
Query query = em.createNativeQuery("select substr(created_at,1,16) created_at, withdraw_number, deposit_number, amount, case when withdraw_number = ? then withdraw_balance else deposit_balance end as \"balance\", case when withdraw_number = ? then '출금' else '입금' end as \"type\" from history_tb where withdraw_number = ? or deposit_number = ?");
query.setParameter(1, number);
query.setParameter(2, number);
query.setParameter(3, number);
query.setParameter(4, number);
List<Object[]> objectList = (List<Object[]>) query.getResultList();
List<AccountResponse.HistoryDTO> historyList = new ArrayList<>();
for (Object[] objects : objectList) {
AccountResponse.HistoryDTO historyDTO = new AccountResponse.HistoryDTO(
(String) objects[0],
(int) objects[1],
(int) objects[2],
(int) objects[3],
(int) objects[4],
(String) objects[5]
);
historyList.add(historyDTO);
}
return historyList;
}
문제 원인
HistoryDTO
클래스에는 생성자가 없음
HistoryDTO
클래스는 @Data
애너테이션을 사용하고 있지만, 명시적인 생성자가 없기 때문에 기본 생성자만 자동으로 생성됩니다.그러나
for
루프에서는 new AccountResponse.HistoryDTO(...)
를 통해 인스턴스를 생성하려고 하므로, 해당 생성자가 없어서 컴파일 오류 또는 런타임 오류가 발생할 수 있습니다.- 타입 변환 문제
(int) objects[1]
같은 형변환에서 문제가 발생할 가능성이 있습니다.objects[1]
,objects[2]
,objects[3]
,objects[4]
등이Integer
,BigDecimal
,Long
등의 타입으로 반환될 수 있습니다.String
으로 저장된 숫자를(int)
로 변환하면ClassCastException
이 발생할 수도 있습니다.
🛠 해결 방법
1. HistoryDTO
에 생성자 추가
AccountResponse.HistoryDTO
클래스에 필요한 모든 필드를 받는 생성자를 추가
@Data
public static class HistoryDTO {
private String createdAt;
private int withdrawNumber;
private int depositNumber;
private int amount;
private int balance;
private String type;
public HistoryDTO(String createdAt, int withdrawNumber, int depositNumber, int amount, int balance, String type) {
this.createdAt = createdAt;
this.withdrawNumber = withdrawNumber;
this.depositNumber = depositNumber;
this.amount = amount;
this.balance = balance;
this.type = type;
}
}
2. 타입 변환 문제 해결
JPA의
createNativeQuery()
는 필드 값을 Object[]
형태로 반환하는데, 숫자 값이 BigDecimal
또는 Long
으로 반환될 수 있습니다.따라서
(int) objects[i]
대신에 ((Number) objects[i]).intValue()
를 사용하면 타입 변환 문제를 방지할 수 있습니다.- 수정된 코드
for (Object[] objects : objectList) {
AccountResponse.HistoryDTO historyDTO = new AccountResponse.HistoryDTO(
(String) objects[0],
((Number) objects[1]).intValue(),
((Number) objects[2]).intValue(),
((Number) objects[3]).intValue(),
((Number) objects[4]).intValue(),
(String) objects[5]
);
historyList.add(historyDTO);
}
결론
HistoryDTO
클래스에 모든 필드를 받는 생성자를 추가
(int) objects[i]
대신((Number) objects[i]).intValue()
를 사용하여 타입 변환 문제를 해결
Share article