Почему мне нужно синхронизировать c двунаправленную связь даже с CascadeType.PERSIST, используя Spring Data JPA - PullRequest
0 голосов
/ 29 мая 2020

Вот пример кода, демонстрирующий проблему:

Сущность еды:

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

Сущности Meal и Food сохраняются благодаря CascadeType.PERSIST, но столбец meal_id остается пустым, если я явно не устанавливаю meal в сущность Meal.

Это не то поведение, которое я ожидал бы, и мне интересно, почему это не выполняется автоматически для меня.

1 Ответ

1 голос
/ 30 мая 2020
@Entity
public class Meal {


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

} 

Здесь mappedBy означает, что значение поля meal в Food используется для предоставления значения для соответствующего столбца базы данных, связывающего Food и Meal (т.е. meal_id столбец в таблице Food). Поэтому, если вы не установите его, он всегда останется NULL.

С другой стороны, без mappedBy означает, что значение поля foods в Meal используется для предоставления значения для столбца meal_id. Причина ручной синхронизации c. им просто нужна согласованная модель 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...