개선 전 코드
BidProductResponseDto가 생성될 때 경매 상품의 제시자가 아무도 없어 topBid가 null인 경우 NPE가 발생했다.
public BidProductResponseDto(BidProduct bidProduct) {
id = bidProduct.getId();
name = bidProduct.getName();
description = bidProduct.getDescription();
startPrice = bidProduct.getStartPrice();
expirationPeriod = bidProduct.getExpirationPeriod();
feetSize = bidProduct.getFeetsize();
footSize = bidProduct.getFootsize();
footPicture = bidProduct.getFootpicture();
brand = new BrandResponseDto(bidProduct.getBrand());
topBid = new BidResponseDto(bidProduct.getTopBid());
status = bidProduct.getStatus();
createdAt = bidProduct.getCreatedAt();
updatedAt = bidProduct.getUpdatedAt();
for (int i = 0; i < bidProduct.getBids().size(); i++) {
bidResponseDtoList.add(new BidResponseDto(bidProduct.getBids().get(i)));
}
}
해결방안
입찰이 하나도 없을 때 빈 객체를 생성한 뒤, topBid의 제시자는 경매상품 출품자로, topBid의 가격은 경매 시작가로 설정한다.
public BidProductResponseDto(BidProduct bidProduct) {
this.id = bidProduct.getId();
this.name = bidProduct.getName();
this.author = bidProduct.getUser().getName();
this.description = bidProduct.getDescription();
this.startPrice = bidProduct.getStartPrice();
this.expirationPeriod = bidProduct.getExpirationPeriod();
this.feetSize = bidProduct.getFeetsize();
this.footSize = bidProduct.getFootsize();
this.footPicture = bidProduct.getFootpicture();
this.brand = new BrandResponseDto(bidProduct.getBrand());
// topBid 설정 (경매 제시가가 아직 없을 경우 처리)
if (bidProduct.getTopBid() != null) {
this.topBid = bidProduct.getTopBid();
} else {
// topBid가 없을 때 topBid 제시자는 경매상품 등록자로, 가격은 startPrice로 설정
this.topBid = new Bid();
this.topBid.setUser(bidProduct.getUser());
this.topBid.setBidPrice(bidProduct.getStartPrice());
}
this.status = bidProduct.getStatus();
this.createdAt = bidProduct.getCreatedAt();
this.updatedAt = bidProduct.getUpdatedAt();
this.bidResponseDtoList = bidProduct.getBids().stream()
.map(BidResponseDto::new)
.sorted(Comparator.comparing(BidResponseDto::getBidPrice))
.toList();
}
고찰할 점
@Table(name = "bidproduct")
public class BidProduct extends Timestamped{
...
/**
* 연관관계 - Foreign Key 값을 따로 컬럼으로 정의하지 않고 연관 관계로 정의합니다.
*/
@OneToMany(mappedBy = "bidProduct", cascade = CascadeType.REMOVE)
private List<Bid> bids = new ArrayList<>();
@OneToOne
@JoinColumn(name = "topBid")
private Bid topBid;
...
}
BidProduct와 topBid는 일대일 단방향 연관관계인데 topBid가 null인 경우를 (topBid의 price가 null인 경우, topBid의 user가 null인 경우 등등..) 메서드마다 매번 핸들링해줘야 했다. 아예 topBid의 초기값을 설정하는 게 더 나은 방법이었을까?