1:N 연관관계에서 지연 로딩(lazy)을 사용하는 경우 발생할 수 있는 에러.
지연 로딩의 경우 필요한 시점에 데아터를 불러 온다.
그 전까지는 proxy 객체가 들어있는데 -> proxy를 serialize(직렬화)할 수 없기 때문에 발생하는 에러!
// settlement와 contract는 1:N 관계
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Settlement {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 계약서
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "contractId")
private Contract contract;
...
}
// 서비스 코드
public List<SettlementDto> test(Long type, Long id, LocalDate date) {
List<Settlement> settlementList = settlementRepository.test(type, id, date);
List<SettlementDto> settlementDtoList = settlementList.stream()
.map(SettlementDto::of)
.toList();
return settlementDtoList;
}
이런식으로 바로 호출하게 되면 에러 발생.
settlementDto 객체에 들어있는 Contract는 proxy인 상태.
dto를 만들어 초기화를 하자.
SettlementDto를 이런식으로 작성해서 Contract에서 필요한 요소만 추출하자.
@Getter
@Setter
@ToString
@NoArgsConstructor
public class SettlementDto {
// Contract가 아닌 ContractDto을 새로 만들기
private ContractDto contractDto;
private Long type;
private Long memberId;
private LocalDateTime settleDate;
private Double fee;
@Builder
public SettlementDto(ContractDto contractDto, Long type, Long memberId, LocalDateTime settleDate, Double fee) {
this.contractDto = contractDto;
this.type = type;
this.memberId = memberId;
this.settleDate = settleDate;
this.fee = fee;
}
public static SettlementDto of (Settlement settlement) {
ContractDto contractDto = ContractDto.of(settlement.getContract());
return SettlementDto.builder()
.contractDto(contractDto)
.type(settlement.getType())
.memberId(settlement.getMemberId())
.settleDate(settlement.getSettleDate())
.fee(settlement.getFee())
.build();
}
}