首页 > 解决方案 > Jpa 无法将 json 映射到每次都重新创建的实体

问题描述

我有一个包含 3 个实体的项目,如示例中所示:

1:

@Entity
@Table(name = "GOAL")
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class GoalEntity implements Length {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "GOAL_ID", nullable = false, updatable = true)
    @EqualsAndHashCode.Include
    private Long id;

    @Column(name = "NAME", length = NAME)
    private String name;

    @OneToMany(mappedBy = "goal", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<GoalQuestionEntity> goalQuestions;

}

2:

@Entity
@Table(name = "GOAL_QUESTION")
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class GoalQuestionEntity implements MprcMaxLength {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
//    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "GOAL_QUESTION_ID", nullable = false, updatable = false)
    @EqualsAndHashCode.Include
    private Long id;

    @Column(name = "TITLE", length = NAME)
    private String title;

    @Column(name = "DESCRIPTION", length = NAME)
    private String description;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "GOAL_ID")
    private GoalEntity goal;

    @OneToMany(mappedBy = "goalQuestion", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<GoalQuestionAnswerEntity> goalQuestionAnswers;

}

3:

@Entity
@Table(name = "GOAL_QUESTION_ANSWER")
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class GoalQuestionAnswerEntity implements MprcMaxLength {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "GOAL_QUESTION_ANSWER_ID", nullable = false, updatable = false)
    @EqualsAndHashCode.Include
    private Long id;

    @Column(name = "TEXT", length = NAME)
    private String text;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "GOAL_QUESTION_ID")
    private GoalQuestionEntity goalQuestion;

}

和一个存储库:

@Repository
public interface GoalJpaRepository extends JpaRepository<GoalEntity, Long> {

}

现在,我想每次传递整个数据结构时都从前端调用一个api,如下所示:

[
  {
    "id": 25,
    "name": "goal 1",
    "goalQuestions": [
      {
        "id": 21,
        "title": "title",
        "description": "desc",
        "goalQuestionAnswers": [{
          "id": null,
          "text": "hello"
        }
      ]
      }
    ]
  },
  {
    "id": 26,
    "name": "goal 2",
    "goalQuestions": null
  },
  {
    "id": 27,
    "name": "goal 3",
    "goalQuestions": null
  }
]

如果我传递一个空或不存在的实体 ID,我想创建一个新实体,如果 ID 已保存,我想更新该实体。否则我想删除实体。可以用jpa做到这一点吗?

这是我正在使用的服务中的更新方法:

public List<GoalResponse> update(List<GoalRequest> goalRequestList) {
//        goalJpaRepository.deleteAll();

        List<GoalEntity> goalEntityList = goalRequestList.stream().map(goalRequest -> {
            GoalEntity goalEntity = goalJpaRepository.findById(goalRequest.getId()).orElse(new GoalEntity());
            questionsHelper.mapRequestToEntity(goalRequest, goalEntity);
            return goalEntity;
        }).collect(Collectors.toList());

        goalEntityList = goalJpaRepository.saveAll(goalEntityList);

        return goalEntityList.stream().map(questionsHelper::mapEntityToResponse).collect(Collectors.toList());
    }

这是映射方法:

public GoalEntity mapRequestToEntity(GoalRequest goalRequest, GoalEntity goalEntity) {
        goalEntity.setId(goalRequest.getId());
        goalEntity.setName(goalRequest.getName());
        if (CollectionUtils.isNotEmpty(goalRequest.getGoalQuestions())) {
            if (goalEntity.getGoalQuestions() == null) {
                goalEntity.setGoalQuestions(new LinkedList<>());
            }
            goalEntity.getGoalQuestions().clear();
            goalEntity.getGoalQuestions().addAll(mapGoalQuestionsRequestToEntity(goalRequest.getGoalQuestions(), goalEntity));
        }
        return goalEntity;
    }

private List<GoalQuestionEntity> mapGoalQuestionsRequestToEntity(List<GoalQuestionRequest> goalQuestionsRequests, GoalEntity goalEntity) {
        List<GoalQuestionEntity> goalQuestionEntities = goalQuestionsRequests
                .stream()
                .map(goalQuestionRequest -> {
                    GoalQuestionEntity goalQuestionEntity = new GoalQuestionEntity();

                    goalQuestionEntity.setId(goalQuestionRequest.getId());
                    goalQuestionEntity.setTitle(goalQuestionRequest.getTitle());
                    goalQuestionEntity.setDescription(goalQuestionRequest.getDescription());

                    goalQuestionEntity.setGoal(goalEntity);

                    if (CollectionUtils.isNotEmpty(goalQuestionRequest.getGoalQuestionAnswers())) {
                        if (goalQuestionEntity.getGoalQuestionAnswers() == null) {
                            goalQuestionEntity.setGoalQuestionAnswers(new LinkedList<>());
                        }
                        goalQuestionEntity.getGoalQuestionAnswers().clear();
                        goalQuestionEntity.getGoalQuestionAnswers().addAll(mapGoalQuestionAnswerRequestToEntity(goalQuestionRequest.getGoalQuestionAnswers(), goalQuestionEntity));
                    }

                    return goalQuestionEntity;
                }).collect(Collectors.toList());
        return goalQuestionEntities;
    }

private List<GoalQuestionAnswerEntity> mapGoalQuestionAnswerRequestToEntity(List<GoalQuestionAnswerRequest> goalQuestionAnswersRequests, GoalQuestionEntity goalQuestionEntity) {
        List<GoalQuestionAnswerEntity> goalQuestionAnswersEntities = goalQuestionAnswersRequests
                .stream()
                .map(goalQuestionAnswerRequest -> {
                    GoalQuestionAnswerEntity goalQuestionAnswerEntity = new GoalQuestionAnswerEntity();
                    goalQuestionAnswerEntity.setId(goalQuestionAnswerRequest.getId());
                    goalQuestionAnswerEntity.setText(goalQuestionAnswerRequest.getText());

                    goalQuestionAnswerEntity.setGoalQuestion(goalQuestionEntity);

                    return goalQuestionAnswerEntity;
                })
                .collect(Collectors.toList());
        return goalQuestionAnswersEntities;
    }

问题是我收到错误 A collection with cascade="all-delete-orphan" is no longer referenced by the owning entity instance...

很抱歉这么长的信息,谢谢您的帮助

标签: javahibernatejpaspring-data-jpa

解决方案


推荐阅读