【问题标题】:Why do I have to sync a bidirectional relationship even with CascadeType.PERSIST using Spring Data JPA为什么即使使用 Spring Data JPA 与 CascadeType.PERSIST 也必须同步双向关系
【发布时间】:2020-09-17 11:03:10
【问题描述】:

这是一个演示该问题的示例代码:

膳食实体:

@Entity
public class Meal {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;

  @OneToMany(mappedBy = "meal", cascade = CascadeType.PERSIST)
  private Collection<Food> foods;

  public Meal() {
    foods = new HashSet<>();
  }

  public Collection<Food> getFoods() {
    return foods;
  }

  public void addFood(Food food) {
    foods.add(food);
    // without this the `meal_id` column is null
    food.setMeal(this);
  }
}

食品实体:

@Entity
public class Food {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;

  @ManyToOne
  private Meal meal;

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public Meal getMeal() {
    return meal;
  }

  public void setMeal(Meal meal) {
    this.meal = meal;
  }
}

这里是创建和保存实体的代码:

Meal meal = new Meal();

for (int i = 0; i < 10; i++) {
  meal.addFood(new Food());
}

mealRepository.save(meal);

由于CascadeType.PERSIST,Meal 和 Food 实体都保持不变,但如果我没有将 meal 字段显式设置为 Meal 实体,meal_id 列将保持为空。

这不是我所期望的行为,我想知道为什么这不是自动为我完成的。

【问题讨论】:

  • 很多事情不是自动为你完成的,所以你只是有错误的期望。为什么它会自动完成,因为foods.add(food); 不是自动完成的?程序员最终对程序的工作负责,因此在双向映射等棘手的情况下阅读文档是必不可少的。
  • 我投票结束这个问题,因为它按设计工作。
  • 当问题是为什么时,@Kayaman“按设计工作”并不是真正的答案。我知道你不知道答案,也许其他人会。
  • 这不是答案,而是关闭的理由。你的问题是“为什么它不像我想的那样工作?”对此没有很好的答案。除非您阅读过文档,否则您会知道它是如何工作的,并且您不会有错误的期望。不要假设事情会像你想的那样工作。像所有优秀的软件开发人员一样阅读文档。
  • @Kayaman 我建议您研究 DX(开发人员体验)。开发人员的优秀软件工具大部分时间都按预期工作。一位开发人员曾经做出了设计决定,我很好奇是什么导致了这个决定,这就是我的问题所在。

标签: java spring database hibernate jpa


【解决方案1】:
@Entity
public class Meal {


  @OneToMany(mappedBy = "meal", cascade = CascadeType.PERSIST)
  private Collection<Food> foods;

} 

这里的mappedBy表示Foodmeal字段的值用于为FoodMeal之间链接的对应数据库列提供值(即@中的meal_id列987654328@表)。所以如果你不设置它,它会一直保持为NULL。

另一方面,没有mappedBy 意味着Meal 中的foods 字段的值用于为meal_id 列提供值。手动同步它们的原因只是为了使用一致的 OOP 模型。

CascadeType.PERSIST 与设置实体的值无关。它永远不会为您更新实体的价值。它的帮助是在相关实体上自动调用一些entityManager 方法。没有它,您必须调用以下命令来保存所有食物和膳食:

entityManager.persist(meal);
entityManager.persist(food1);
entityManager.persist(food2);
......
entityManager.persist(foodN);

有了它,你只需调用

entityManager.persist(meal);

entityManager.persist(foodN) 的其余部分将被“级联”以自动调用。

所以就 spring-data-jpa 而言,而不是调用

mealRepository.save(meal);
foodRepository.persist(food1);
foodRepository.persist(food2);
......
foodRepository.persist(foodN);

你只需要打电话

mealRepository.save(meal);

【讨论】:

    猜你喜欢
    • 2020-06-05
    • 2015-08-08
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多