HHH000327: Error performing load command 해결하기

까망새부리·2022년 5월 8일
0

Spring을 활용하여 개인 프로젝트의 back end 서버를 개발하면서 조회 기능을 만들던 중에 다음과 같은 에러를 확인했다.

에러는 2개의 Entity가 @OneToMany로 연결이 되었을 때, 조회를 하는 과정에서 발생했던 문제였다. 에러가 발생했던 코드와 두개의 Entity는 다음과 같은 형태였다.

Error가 발생했던 함수

  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);
  }

ChartData Entity

@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 + ")";
  }
}

DataCategory Entity

@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은 LAZYEAGAR이 있으며 각각 지연로딩과 즉시로딩을 의미한다.

지연로딩(LAZY)

  • 데이터를 조회할 때, 필요할 때 연관된 데이터를 불러오는 형태
  • 연관된 엔티티를 프록시로 조회한다. 프록시를 실제로 사용할 때 초기화를 진행하면서 DB를 조회한다.

즉시로딩(EAGAR)

  • 데이터를 조회할 때, 연관된 데이터를 한 번에 불러오는 형태
  • Hibernate는 가능하면 SQL JOIN을 사용해서 한 번에 조회한다.

profile
배움을 찾는 사람이 되자!

0개의 댓글