@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Portfolio {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@OneToMany(mappedBy = "parent" ,fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private Set<PortfolioChildMap> parents;
}
@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PortfolioChildMap {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@ManyToOne
@JsonBackReference
@JoinColumn(name = "parent_id")
private Portfolio parent;
@ManyToOne
@JoinColumn(name = "child_id")
private Portfolio child;
}
@Data
@Builder
public class PortfolioResponseDto {
private Integer id;
private List<PortfolioResponseDto> children;
public static PortfolioResponseDto toDTO(Portfolio entity) {
return PortfolioResponseDto.builder()
.id(entity.getId())
.children(entity.getParents().stream().map(parent-> toDTO(parent.getChild())).collect(Collectors.toList()))
.build();
}
}
public class PortfolioService {
private final PortfolioRepository portfolioRepository;
@Override
public List<PortfolioResponseDto> getAllPortfolios() {
return portfolioRepository.findAll().stream()
.map(PortfolioResponseDto::toDTO).collect(Collectors.toList());
}
}
Таблица портфолио_child_map
Как вы можете видеть, между портфолио с идентификаторами 33 и 34 есть кружок. Родительский Portfolio.id=33 имеет дочерний Portfolio.id=34, а также Родительский Portfolio.id=34 имеет дочерний Portfolio.id=33, и это круг.
Когда я вызываю PortfolioService.getAllPortfolios(), это вызывает ошибку в методе PortfolioResponseDto.toDTO.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause java.lang.StackOverflowError: null
Я почти уверен, что это распространенная ошибка, но я не знаю, как ее исправить. Итак, у меня есть два вопроса:
Как правильно исправить эту проблему, как избежать подобных ошибок.
В моем случае это нормально, что я получил первого ребенка от родителя и остановился. Я не знаю, как это сделать. Должен ли я реализовать собственный метод findAll в репозитории?
да, это возможен сценарий в моем домене
По сути, это не является неотъемлемой частью сопоставления вашей сущности. Это просто случай бесконечной рекурсии. Это означает, что вам необходимо предотвратить возникновение бесконечной рекурсии. Есть несколько вариантов... Вы можете либо...
Третий вариант «карта одного уровня» — именно то, что мне нужно. Знаете ли вы, как это реализовать в моем случае? Я предполагаю, что мне нужно удалить свойства родителей и активов из сущности портфеля и реализовать собственный метод на уровне репозитория, чтобы получить первого дочернего элемента?
Сопоставьте идентификатор родителя (возможно, также немного дополнительных метаданных, если вы этого хотите или нуждаетесь в этом). Тогда вообще не картируйте детей. Если вы хотите или нуждаетесь в детях, позвоните отдельно. В случае, когда вам нужен родительский элемент, у вас есть идентификатор родителя, и вы можете просто загрузить его по идентификатору. В случае, когда вам нужны дочерние элементы, вам нужен репозиторий, в который вы можете просто загрузить текущий идентификатор, а затем перейти к дочерним элементам. Затем вы можете сопоставить их и вернуть результат.
У меня есть два комментария: во-первых, похоже, что вы используете рекурсивный дизайн, и, возможно, это поможет сформулировать ваш запрос: web.csulb.edu/colleges/coe/cecs/dbdesign/…. А во-вторых, мне кажется странным, что X может быть родителем Y и в то же время противоположным (Y родителем X). Реален ли такой сценарий в вашей сфере?