簡體   English   中英

JPA Hibernate-級聯刪除數據庫和注釋

[英]JPA Hibernate - cascade delete in both database and annotation

簡要

我想知道應該怎么做,因為我讀了許多試圖理解這一點的文章,包括許多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;
  }

}

問題

如果我現在在Foo對象上調用刪除操作(通過EntityManagerFactorySessionFactory ),將發生以下哪項?

  1. 休眠操作將刪除bar表中外鍵為Foofoo_id所有記錄,然后刪除Foo記錄。

  2. 休眠操作將刪除已加載到會話高速緩存中的所有對應的Bar記錄(可能是也可能不是實際數據庫中存在的所有bar記錄),然后刪除Foo記錄(數據庫級聯規則將刪除所有剩余的bar記錄)。

  3. 休眠操作將首先嘗試刪除Foo記錄,如果數據庫失敗,請執行上述步驟之一。

  4. 發生了我沒有考慮過的其他事情,如果是的話,該怎么辦?

考慮以下困境假設,最佳方法是什么?

Dilemna

如果1為true,則表明:

A)僅在數據庫中定義級聯規則。 確保從應用程序中的對象中刪除bars ,以免它們與數據庫分離(因為數據庫將刪除其記錄),然后調用delete foo

要么

B)僅在應用程序中定義級聯規則,因為它將完全管理數據庫的完整性。

C)在兩者中都定義級聯規則,因為每個規則都可以達到期望的結果,而另一個則浪費了處理。

如果2為true,則表明:

在數據庫和應用程序中定義級聯規則,以便Hibernate可以管理其實體,並且可以保證數據庫可以在此之后清理,因為不能保證應用程序會刪除所有bar記錄。

如果3為true,則表明:

因為Hibernate似乎支持已經在數據庫級別定義的級聯規則,所以在數據庫和應用程序中都定義了級聯規則。

如果4為true,則表明:

這個問題甚至更重要,因為我錯過了一些基本知識!

編輯:添加我已閱讀的文章...

相關文章

數據庫,應用程序或兩者的視圖沖突:

所以-我應該讓JPA或數據庫級聯刪除

數據庫或應用程序的視圖沖突:

所以-級聯刪除使用JPA或在數據庫內部更新

本文闡明了JPA提供程序的實際作用(盡管應注意,他們使用OpenJPA提供程序來進行操作證明):

日本教程

它指出:

刪除和持久操作的級聯也適用於那些尚未加載的實體。 它甚至通過它們傳遞給其他實體,從而有可能遍歷整個對象圖。

它繼續說明:

刷新,合並和分離的級聯僅通過已加載的實體進行。

這意味着提議的過程2是不正確的。

如果在數據庫中聲明了層疊並進入休眠狀態,則數據庫將始終首先刪除(如果它支持它),並且休眠調用實際上並不會刪除任何內容,而是無論如何都會運行。 但是,由於使用的是休眠模式,因此它的主要優點是可以輕松過渡到可能不支持數據庫端級聯功能的新數據庫。 因此,即使數據庫支持級聯並且休眠的下划線jdbc語句當前未執行任何操作(將來可能會執行某些操作),您也希望將它們保留在此處

你為什么還要考慮呢? 最好堅持使用休眠級聯選項。 在另一邊具有級聯的另一端將運行級聯刪除兩次。 一次從休眠狀態,一次由數據庫管理。

例189.來自hibernate 5.2文檔。 生成下面的sql。

@Entity(name = "Person")
public static class Person {
    @ManyToMany(cascade = {CascadeType.DELETE})
    private List<Address> addresses = new ArrayList<>();
    ...
}

Person person1 = entityManager.find( Person.class, personId );
entityManager.remove( person1 );
DELETE FROM Person_Address
WHERE  Person_id = 1

DELETE FROM Person
WHERE  id = 1

現在您看到休眠在刪除父實體之前先刪除子實體。 數據庫級聯將在sql person delete上運行,但是當以前刪除子級時,現在沒有什么可刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM