Hibernate中的JPA 2.1条件删除/更新和临时表
從JPA 2.0版開始, EntityManager提供了方法getCriteriaBuilder()來動態(tài)構(gòu)建選擇查詢,而無需使用Java持久性查詢語言(JPQL)進行字符串連接。 在2.1版中,此CriteriaBuilder提供了兩個新方法createCriteriaDelete()和createCriteriaUpdate() ,使我們可以使用條件API制定刪除和更新查詢的方法。
出于說明目的,讓我們對兩個實體Person和Geek使用簡單的繼承用例:
要從我們的數(shù)據(jù)庫中刪除所有喜歡Java作為其編程語言的怪胎,我們可以使用EntityManager的新createCriteriaDelete()方法利用以下代碼:
EntityTransaction transaction = null; try {transaction = entityManager.getTransaction();transaction.begin();CriteriaBuilder builder = entityManager.getCriteriaBuilder();CriteriaDelete<Geek> delete = builder.createCriteriaDelete(Geek.class);Root<Geek> geekRoot = delete.from(Geek.class);delete.where(builder.equal(geekRoot.get("favouriteProgrammingLanguage"), "Java"));int numberOfRowsUpdated = entityManager.createQuery(delete).executeUpdate();LOGGER.info("Deleted " + numberOfRowsUpdated + " rows.");transaction.commit(); } catch (Exception e) {if (transaction != null && transaction.isActive()) {transaction.rollback();} }與純SQL一樣,我們可以使用from()方法指定要針對其發(fā)出刪除查詢的表,并使用where()聲明謂詞。 通過這種方式,標準API允許以動態(tài)方式定義批量刪除操作,而無需使用過多的字符串連接。
但是,SQL是如何創(chuàng)建的呢? 首先,ORM提供程序必須注意,我們正在使用策略JOINED從繼承層次結(jié)構(gòu)中刪除,這意味著我們有兩個表T_PERSON和T_GEEK ,其中第二個表存儲對父表的引用。 Hibernate版本4.3.8.Final創(chuàng)建以下SQL語句:
insert intoHT_T_GEEKselectgeek0_.id as id fromT_GEEK geek0_ inner joinT_PERSON geek0_1_ on geek0_.id=geek0_1_.id wheregeek0_.FAV_PROG_LANG=?;delete fromT_GEEK where(id) IN (selectid fromHT_T_GEEK);delete fromT_PERSON where(id) IN (selectid fromHT_T_GEEK)delete fromHT_T_GEEK;如我們所見,Hibernate使用與我們的搜索條件匹配的極客/人員的ID填充了一個臨時表。 然后,它將刪除極客表中的所有行,然后刪除人員表中的所有行。 最后,臨時表被清除。
刪除語句的順序很明確,因為表T_GEEK在T_PERSON表的id列上具有外鍵約束。 因此,子表中的行必須在父表中的行之前刪除。 本文介紹了Hibernate創(chuàng)建臨時表的原因。 概括起來,潛在的問題是查詢限制了僅在子表中存在的列上要刪除的行。 但是子表中的行必須在父表中的相應行之前刪除。 刪除子表中的行(即,所有具有FAV_PROG_LANG='Java'的怪胎)后,由于已經(jīng)刪除了怪胎行,因此無法隨后刪除所有對應的人員。 解決該問題的方法是臨時表,該臨時表首先收集應刪除的所有行ID。 知道所有ID后,可以使用此信息先從怪胎表中刪除行,然后從人員表中刪除行。
上面生成的SQL語句當然獨立于標準API的用法。 使用JPQL方法會導致生成相同的SQL:
EntityTransaction transaction = null; try {transaction = entityManager.getTransaction();transaction.begin();int update = entityManager.createQuery("delete from Geek g where g.favouriteProgrammingLanguage = :lang").setParameter("lang", "Java").executeUpdate();LOGGER.info("Deleted " + update + " rows.");transaction.commit(); } catch (Exception e) {if (transaction != null && transaction.isActive()) {transaction.rollback();} }當我們將繼承策略從JOINED更改為SINGLE_TABLE ,生成的SQL語句也更改為單個(此處的鑒別DTYPE列為DTYPE ):
delete fromT_PERSON whereDTYPE='Geek' and FAV_PROG_LANG=?結(jié)論
用于刪除和更新的標準API的新增功能使您可以構(gòu)造SQL語句,而無需任何字符串連接。 但是請注意,從繼承層次結(jié)構(gòu)中進行批量刪除可能會迫使基礎(chǔ)ORM使用臨時表,以便組裝必須事先刪除的行列表。
翻譯自: https://www.javacodegeeks.com/2015/02/jpa-2-1-criteria-deleteupdate-temporary-tables-hibernate.html
總結(jié)
以上是生活随笔為你收集整理的Hibernate中的JPA 2.1条件删除/更新和临时表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 换宽带了路由器怎么重新设置方法红米路由器
- 下一篇: 在Websphere 8.0上安装Lif