Отношения JPA не обновляются при удалении детей - PullRequest
5 голосов
/ 26 апреля 2011

Учитывая следующий сценарий:

@Entity
public class A {
  @OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
  private List<B> bList;
}

@Entity
public class B {
  @ManyToOne()
  @JoinColumn(name = "a_id", referencedColumnName = "id")
  private A a;

  @ManyToOne()
  @JoinColumn(name = "c_id", referencedColumnName = "id")
  private C c;
}

@Entity
public class C {
  @OneToMany(mappedBy="c", cascade=CascadeType.ALL, orphanRemoval=true)
  @CascadeOnDelete // eclipselink specific optimization annotation
  private List<B> bList;
}

Другими словами: и объект A, и объект C содержат несколько объектов B.

Когда я удаляю объект C (технически я обновляю объект, содержащий несколько объектов C и использующий orphanremoval), я хочу удалить все ссылочные B-объекты, что работает, как и ожидалось, с текущими аннотациями. Однако менеджер сущностей, похоже, не понимает, что объект А, лежащий в его кэше, потерял некоторых детей. Если бы у меня был экземпляр A, мне, конечно, пришлось бы обновлять его bList вручную или делать новый запрос, чтобы обновить его, но даже вновь полученные A-объекты все еще устарели. Для повторения:

  • С объекты удалены.
  • Удаление связано с объектами B с помощью orphanRemoval.
  • bList в объектах, кэшированных в Entity Manager, равен , не обновляется .
  • Очистка кэша Entity Managers вручную позволяет получать правильно обновленные объекты.

Как это можно решить? Я бы ожидал, что либо менеджеры сущностей обновят свой постоянный контекст автоматически, либо сделают каскадную аннотацию доступной на @JoinColumn, но, похоже, ни одна из них здесь не подходит.

РЕДАКТИРОВАТЬ: Кажется, что проблема заключается в том, что bList объекта C не обновляется при обновлении bList объекта A (и поэтому не может каскадно меняться). Хотя я понятия не имею, почему .. Тем не менее, обратите внимание, что я говорю о контексте персистентности, а не об экземплярах объектов.

1 Ответ

6 голосов
/ 28 апреля 2011

JPA не выполняет за вас отношения, приложение должно их поддерживать. Это означает, что когда вы удаляете объект, приложение отвечает за очистку любых ссылок на этот объект. Это очевидно, когда это отношение внешнего ключа, поскольку ограничения базы данных обычно вызывают исключение, если это не сделано. Однако в случае обратных ссылок, когда отношения не имеют строгого ограничения базы данных, пользователи, как правило, ошибочно полагают, что JPA справится с этим - оставив кэш поврежденным.

Способ справиться с этим - удалить любые ссылки на объекты C и B. В вашей объектной модели это означает исправление bList A для удаления Bs. Я видел это через события удаления сущности или в коде приложения. Поскольку в этом случае A не имеет внешнего ключа, вы также можете обновить затронутые объекты A из базы данных после того, как произошло удаление (т. Е. После сброса или фиксации).

...