Spring을 활용하여 개인 프로젝트의 back end 서버를 개발하면서 조회 기능을 만들던 중에 다음과 같은 에러를 확인했다.
에러는 2개의 Entity가 @OneToMany
로 연결이 되었을 때, 조회를 하는 과정에서 발생했던 문제였다. 에러가 발생했던 코드와 두개의 Entity는 다음과 같은 형태였다.
public ChartDataDto getChartDataById(Long id) throws ChartDataException {
ChartData chartData = chartDataRepository.findById(id).orElseThrow(
() -> new ChartDataException(ChartDataErrorCode.CANNOT_FOUND_CHART_DATA.getErrorCode(),
ChartDataErrorCode.CANNOT_FOUND_CHART_DATA.getMsg())
);
log.info("chart_data information {}", chartData.toString());
for (var dataCategory : chartData.getDataCategories()) {
log.info("Category information : {}", dataCategory.getCategory().toString());
}
return new ChartDataDto(chartData);
}
@Getter
@Entity
@NoArgsConstructor
public class ChartData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "chartData")
private List<DataCategory> dataCategories;
private int money;
private String itemName;
private String memo;
private LocalDateTime localDateTime;
@Builder
public ChartData(Long id, int money, String itemName, String memo, LocalDateTime localDateTime){
this.id = id;
this.money = money;
this.itemName = itemName;
this.memo = memo;
this.localDateTime = localDateTime;
this.dataCategories = new ArrayList<>();
}
public void setDataCategory(List<DataCategory> dataCategory) {
this.dataCategories = dataCategory;
}
public void updateChartData(ChartDataDto chartDataDto) {
this.money = chartDataDto.getMoney();
this.itemName = chartDataDto.getItemName();
}
public void addDataCategory(DataCategory dataCategory) {
this.dataCategories.add(dataCategory);
}
public ChartData(ChartDataDto chartDataDto) {
this.money = chartDataDto.getMoney();
this.localDateTime = chartDataDto.getLocalDateTime();
this.memo = chartDataDto.getMemo();
this.itemName = chartDataDto.getItemName();
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" +
"id = " + id + ", " +
"money = " + money + ", " +
"itemName = " + itemName + ", " +
"memo = " + memo + ", " +
"localDateTime = " + localDateTime + ")";
}
}
@Builder
@Getter
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class DataCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private ChartData chartData;
@ManyToOne(fetch = FetchType.LAZY)
private Category category;
public static DataCategory createDataCategory(ChartData chartData, Category category) {
DataCategory dataCategory = new DataCategory();
dataCategory.setCategory(category);
dataCategory.setChartData(chartData);
return dataCategory;
}
public static DataCategory createDataCategory(ChartData chartData) {
DataCategory dataCategory = new DataCategory();
dataCategory.setChartData(chartData);
return dataCategory;
}
public static DataCategory createDataCategory(Category category) {
DataCategory dataCategory = new DataCategory();
dataCategory.setCategory(category);
return dataCategory;
}
public void setChartData(ChartData chartData) {
this.chartData = chartData;
chartData.addDataCategory(this);
}
public void setCategory(Category category) {
this.category = category;
category.addDataCategory(this);
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" +
"id = " + id + ")";
}
}
테스트를 하는 과정에서 chartData.getDataCategories()
함수를 실행하는 과정에서 발생했고 이런 문제가 발생했던 이유는 @ManyToOne(fetch = FetchType.LAZY)
때문이었다.
ManyToOne(fetch = FetchType.LAZY)
를 ManyToOne(fetch = FetchType.EAGAR)
변경함으로써 에러를 해결할 수 있었다.
여기서의 FetchType은 LAZY
와 EAGAR
이 있으며 각각 지연로딩과 즉시로딩을 의미한다.
필요할 때
연관된 데이터를 불러오는 형태한 번에 불러오는
형태SQL JOIN
을 사용해서 한 번에 조회한다.