JPA Hibernate - каскадное удаление как в базе данных, так и в аннотации

Краткое

Мне интересно, что я должен делать, поскольку я прочитал много статей, пытающихся понять это, в том числе много вопросов SO. Ничто из того, что я прочитал, не поразило гвоздь на голове этим.

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

Примеры таблиц

create table foo(
  id int unsigned not null auto_increment,
  primary key(id)
);

create table bar(
  id int unsigned not null auto_increment,
  foo_id int unsigned not null,
  primary key(id),
  foreign key(foo_id) references foo(id) on delete cascade on update cascade
)

Примеры классов

@Entity
@Table(name = "foo")
public class Foo {

  private int id;
  private List<Bar> bars;

  @Id
  @GeneratedValue
  @Column(name = "id")
  public int getId() {
    return id;
  }

  @OneToMany(mappedBy = "foo", cascade = {CascadeType.ALL})
  public List<Bar> getBars() {
    return bars;
  }

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

  public void setBars(List<Bar> bars) {
    this.bars = bars;
  }

}

@Entity
@Table(name = "bar")
public class Bar {

  private int id;
  private Foo foo;

  @Id
  @GeneratedValue
  @Column(name = "id")
  public int getId() {
    return id;
  }

  @ManyToOne
  @JoinColumn(name = "foo_id", nullable = false)
  public getFoo() {
    return foo;
  }

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

  public void setFoo(Foo foo) {
    this.foo = foo;
  }

}

Вопросы

Если я теперь вызываю операцию удаления (будь то через EntityManagerFactory или SessionFactory) в объекте Foo, что из следующего произойдет?

  • Операция спящего режима приведет к удалению всех записей в таблице bar внешним ключом которого является Foo foo_id, а затем удалить запись Foo.

  • Операция спящего режима удалит все соответствующие записи bar, которые были загружены в кеш сеанса (который могут или не могут быть все bar записи, которые существуют в фактической базе данных) и затем удалите запись Foo (правило каскада базы данных затем удалит все оставшиеся записи bar).

  • Операция спящего режима будет пытаться сначала удалите запись Foo, а если сбой базы данных, выполните одно из вышеупомянутые шаги.

  • Что-то еще происходит, для которого я не рассматривал, если да что?

Принимая во внимание следующие допущения дилеммы, какой наилучший подход?

Dilemna

Если 1 истинно, это предполагает:

A) Определить каскадное правило только в базе данных. Обязательно удалите bars из объекта в приложении, чтобы они не были отделены от базы данных (поскольку база данных удалит их записи), затем сделайте вызов для удаления Foo.

ИЛИ

B) Определить каскадное правило в приложении только потому, что он полностью контролирует целостность базы данных.

НЕ

C) Определите каскадные правила в обоих случаях, так как каждый достигнет желаемого результата, сделав другой ненужной обработкой.

Если 2 истинно, это предполагает:

Определите каскадные правила как в базе данных, так и в приложении, чтобы Hibernate мог позаботиться об управлении своими сущностями, и база данных может очиститься после того, как приложение не гарантирует удаление всех записей bar.

Если значение 3 истинно, это предполагает:

Определите каскадные правила как в базе данных, так и в приложении, так как Hibernate, похоже, поддерживает правило каскада, которое уже определено на уровне базы данных.

Если значение 4 истинно, это предполагает:

Этот вопрос еще более важен, поскольку я пропустил что-то фундаментальное!

Изменить: Добавить статьи, которые я прочитал...

Статьи по теме

Конфликтные представления для базы данных, приложения или обоих:

SO-should-i-let-jpa-or-the- базы данных каскадных удалений

Конфликтные представления для базы данных или приложения:

SO-cascading-deletes-updates-using-jpa-or- внутри-из-баз данных

Эта статья проливает свет на то, что на самом деле делают провайдеры JPA (хотя следует отметить, что они используют провайдера OpenJPA для подтверждения своих операций):

jpa-tutorial

В нем указано, что:

Каскадирование операций удаления и сохранения применяется также к тем объекты, которые еще не загружены. Он даже проходит через них другие объекты, потенциально проходящие через весь граф объекта.

Далее говорится:

Каскадирование обновления, слияния и отсоединения проходит только через объекты, которые уже загружены.

Это означало бы, что предлагаемый процесс 2 не соответствует действительности.

Ответ 1

если вы объявляете каскад в базе данных и спящий режим, база данных всегда будет удаляться сначала, если она поддерживает ее, а вызовы спящего режима на самом деле ничего не будут удалять, кроме как запускать в любом случае. Однако, поскольку вы используете спящий режим, его основным преимуществом является возможность легкого перехода на новую базу данных, которая может не поддерживать возможности каскадной поддержки базы данных. Таким образом, вы захотите оставить их там, даже если ваша база данных поддерживает каскад, а hibeate, подчеркивающие jdbc-инструкции, в настоящее время ничего не делают (они могут что-то делать в будущем)