日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Hibernate(JPA)一键式删除

發(fā)布時間:2023/12/3 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Hibernate(JPA)一键式删除 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在舊版本的Hibernate中,我可以看到手冊中指示的一鍵式刪除 。 但是較新的版本不再包含此部分。 我不知道為什么。 因此,在這篇文章中,我來看看它是否仍然有效。

一鍵式刪除部分顯示:

有時一個接一個地刪除收集元素可能效率極低。 對于新的空集合(例如,如果您調(diào)用list.clear() ,Hibernate不會這樣做。 在這種情況下,Hibernate將發(fā)出一個DELETE 。

假設(shè)您向大小為20的集合中添加了一個元素,然后刪除了兩個元素。 除非集合是一個包,否則Hibernate將發(fā)出一個INSERT語句和兩個DELETE語句。 這當然是可取的。

但是,假設(shè)我們刪除了18個元素,剩下兩個,然后添加了新元素。 有兩種可能的方式進行

  • 一一刪除十八行,然后再插入三行
  • 在一個SQL DELETE刪除整個集合,并一一插入所有五個當前元素

Hibernate不知道第二個選項可能更快。 對于Hibernate來說,如此直觀可能是不希望的,因為這種行為可能會使數(shù)據(jù)庫觸發(fā)器混亂,等等。

幸運的是,您可以隨時通過丟棄(即取消引用)原始集合并返回帶有所有當前元素的新實例化集合來強制執(zhí)行此行為(即第二種策略)。

一擊刪除不適用于映射為inverse="true"集合。

inverse="true"用于(休眠映射)XML。 但是在這篇文章中,我們將看到JPA (以Hibernate為提供者)如何進行“一次性刪除”。

我們將嘗試不同的方法,看看哪種方法會導(dǎo)致一次刪除。

  • 雙向一對多
  • 單向一對多(帶連接表)
  • 單向一對多(無連接表)
  • 單向一對多(使用ElementCollection )
  • 我們將使用具有多個CartItem的Cart實體。

    雙向一對多

    對于這一點,我們從雙方的引用。

    @Entity public class Cart { ...@OneToMany(mappedBy="cart", cascade=ALL, orphanRemoval=true)Collection<OrderItem> items; }@Entity public class CartItem { ...@ManyToOne Cart cart; }

    為了測試這一點,我們?yōu)镃art的表插入一行,為CartItem的表插入三行或更多行。 然后,我們運行測試。

    public class CartTests { ...@Testpublic void testOneShotDelete() throws Exception {Cart cart = entityManager.find(Cart.class, 53L);for (CartItem item : cart.items) {item.cart = null; // remove reference to cart}cart.items.clear(); // as indicated in Hibernate manualentityManager.flush(); // just so SQL commands can be seen} }

    所示的SQL命令將每個項目分別刪除(而不是一次性刪除)。

    delete from CartItem where id=? delete from CartItem where id=? delete from CartItem where id=?

    丟棄原始集合也不起作用。 它甚至引起了異常。

    public class CartTests { ...@Testpublic void testOneShotDelete() throws Exception {Cart cart = entityManager.find(Cart.class, 53L);// remove reference to cartcart.items = new LinkedList<CartItem>(); // discard, and use new collectionentityManager.flush(); // just so SQL commands can be seen} }javax.persistence.PersistenceException:org.hibernate.HibernateException:A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: ….Cart.items

    我用Hibernate 4.3.11和HSQL 2.3.2對此進行了測試。 如果您的結(jié)果有所不同,請點擊評論 。

    單向一對多(帶連接表)

    為此,我們對映射進行了更改。 這將導(dǎo)致創(chuàng)建一個聯(lián)接表。

    @Entity public class Cart { ...@OneToMany(cascade=ALL)Collection<OrderItem> items; }@Entity public class CartItem { ...// no @ManyToOne Cart cart; }

    再次,我們?yōu)镃art的表插入一行,為CartItem的表插入三行或更多行。 我們還必須在連接表( Cart_CartItem )中插入適當?shù)挠涗洝?然后,我們運行測試。

    public class CartTests { ...@Testpublic void testOneShotDelete() throws Exception {Cart cart = entityManager.find(Cart.class, 53L);cart.items.clear(); // as indicated in Hibernate manualentityManager.flush(); // just so SQL commands can be seen} }

    顯示的SQL命令已刪除聯(lián)接表中的關(guān)聯(lián)行(使用一個命令)。 但是表中CartItem的行仍然存在(并且沒有被刪除)。

    delete from Cart_CartItem where cart_id=? // no delete commands for CartItem

    嗯,不完全是我們想要的,因為CartItem表中的行仍然存在。

    單向一對多(無聯(lián)接表)

    從JPA 2.0開始,通過指定@JoinColumn可以避免單向一對多的連接表。

    @Entity public class Cart { ...@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)@JoinColumn(name="cart_id", updatable=false, nullable=false)Collection<OrderItem> items; }@Entity public class CartItem { ...// no @ManyToOne Cart cart; }

    再次,我們?yōu)镃art的表插入一行,為CartItem的表插入三行或更多行。 然后,我們運行測試。

    public class CartTests { ...@Testpublic void testOneShotDelete() throws Exception {Cart cart = entityManager.find(Cart.class, 53L);cart.items.clear(); // as indicated in Hibernate manualentityManager.flush(); // just so SQL commands can be seen} }

    丟棄原始集合也不起作用。 這也導(dǎo)致了相同的異常(如雙向一對多)。

    javax.persistence.PersistenceException:org.hibernate.HibernateException:A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: ….Cart.items

    單向一對多(帶有

    JPA 2.0引入了@ElementCollection 。 這允許與許多側(cè)之中任建立一個一對多關(guān)系@Basic或@Embeddable (即不是@Entity )。

    @Entity public class Cart { ...@ElementCollection // @OneToMany for basic and embeddables@CollectionTable(name="CartItem") // defaults to "Cart_items" if not overriddenCollection<OrderItem> items; }@Embeddable // not an entity! public class CartItem {// no @Id// no @ManyToOne Cart cart;private String data; // just so that there are columns we can set }

    再次,我們?yōu)镃art的表插入一行,為CartItem的表插入三行或更多行。 然后,我們運行測試。

    public class CartTests { ...@Testpublic void testOneShotDelete() throws Exception {Cart cart = entityManager.find(Cart.class, 53L);cart.items.clear(); // as indicated in Hibernate manualentityManager.flush(); // just so SQL commands can be seen} }

    是的 CartItem的關(guān)聯(lián)行在CartItem被刪除。

    delete from CartItem where Cart_id=?

    總結(jié)思想

    使用ElementCollection以單向一對多的方式進行一次刪除( ElementCollection是嵌入式的,而不是實體)。

    在單向一對多聯(lián)接表方案中,刪除聯(lián)接表中的條目不會增加太多價值。

    我不確定為什么一鍵式刪除在Hibernate中起作用(或為什么這樣起作用)。 但是我確實有一個猜測。 那就是底層的JPA提供者不能一口氣刪除,因為它不能確保多端實體不會被其他實體引用。 與ElementCollection不同,多面不是實體,其他實體也不能引用。

    現(xiàn)在,這并不意味著您必須一直使用ElementCollection 。 一次性刪除可能僅適用于聚合根。 在這些情況下,使用Embeddable和ElementCollection可能適合于組成聚合的值對象的集合。 當除去聚合根時,最好也應(yīng)除去“子”對象(并以有效的方式)。

    我希望JPA中有一種方法可以指示子實體是私有的,并且在刪除父實體時可以安全地刪除它們(例如,類似于EclipseLink中的@PrivateOwned )。 讓我們看看它是否將包含在API的將來版本中。

    希望這可以幫助。

    翻譯自: https://www.javacodegeeks.com/2016/07/one-shot-delete-hibernate-jpa.html

    總結(jié)

    以上是生活随笔為你收集整理的使用Hibernate(JPA)一键式删除的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。