JPA:通過查詢創建對象
JPA允許我們在查詢內創建對象,并帶有所需的值:
package com.model;public class PersonDogAmountReport {private int dogAmount;private Person person;public PersonDogAmountReport(Person person, int dogAmount) {this.person = person;this.dogAmount = dogAmount;}public int getDogAmount() {return dogAmount;}public void setDogAmount(int dogAmount) {this.dogAmount = dogAmount;}public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}
}
package com.main;import java.util.List;import javax.persistence.EntityManager;
import javax.persistence.Query;import com.model.PersonDogAmountReport;public class Page13 {@SuppressWarnings('unchecked')public static void main(String[] args) {CodeGenerator.startConnection();CodeGenerator.generateData();EntityManager em = CodeGenerator.getEntityManager();Query query = em.createQuery('select new com.model.PersonDogAmountReport(p, size(p.dogs)) from Person p group by p.id');List<PersonDogAmountReport> persons = query.getResultList();for (PersonDogAmountReport personReport : persons) {System.out.println(personReport.getPerson().getName() + ' has: ' + personReport.getDogAmount() + ' dogs.');}CodeGenerator.closeConnection();}
}
注意,在查詢中我們創建了一個新對象。 好消息是您可以創建任何對象,而不必是一個實體。 您只需要傳遞類的完整路徑,JPA將處理新的類實例化。
對于需要特定字段但實體中不存在這些字段的報表,這是非常有用的功能。
JPQL:批量更新和刪除
有時我們需要執行一個操作來更新表數據庫中的幾行。 例如,更新所有年齡大于70歲的人,并將其定義為老年人。
您可以像這樣運行批量更新/刪除:
package com.main;import javax.persistence.EntityManager;
import javax.persistence.Query;import com.model.Person;public class Page14 {public static void main(String[] args) {CodeGenerator.startConnection();CodeGenerator.generateData();EntityManager em = CodeGenerator.getEntityManager();em.clear();Query query = em.createQuery('update Person p set p.name = 'Fluffy, the destroyer of worlds!'');query.executeUpdate();query = em.createQuery('select p from Person p where p.id = 4');Person person = (Person) query.getSingleResult();System.out.println('My new name is: ' + person.getName());query = em.createQuery('delete from Person p where p.dogs is empty');query.executeUpdate();query = em.createQuery('select p from Person p');System.out.println('We had 6, but was found ' + query.getResultList().size() + ' persons in the database');CodeGenerator.closeConnection();}
}
在這種情況下,級聯選項不會被觸發。 您將無法刪除對象,并希望JPA刪除關系中的級聯對象。 一旦討論批量操作,數據庫數據的完整性就屬于開發人員。 如果要從數據庫及其關系中刪除對象,則需要在執行刪除操作之前將對象的關系更新為null。
我們可以將這種操作定義為非常危險的操作。 如果我們在第17行添加注釋(“ em.clear(); “),我們將看到該人的姓名在更新后仍然保持不變。
“ 問題 ”是持久性上下文將所有數據“ 附加 ”在內存中,但是這些批量操作不會更新持久性上下文。 我們將在數據庫中完成一個操作,但尚未在持久性上下文中反映出來。 這種情況可能會給我們帶來同步問題。
描繪以下場景:
- 事務開始。
- 通過方法em.persist()將人員A保留在數據庫中。
- 人B的名稱通過em.merge()方法更新為“ Louanne”。
- 人員A將通過批量刪除操作被刪除。
- 人B的名稱已通過批量更新更新為“ Fernanda”。
- 交易完成。
在這種情況下會發生什么? 人員A已被批量操作刪除,但是持久性上下文將嘗試將其持久化到數據庫中。 人員B的名稱已更新為Fernanda,但“持久性上下文”將嘗試更新為Louanne。
對于某種情況,沒有默認行為,但是可以使用一些解決方案來避免這些問題:
- 在批量操作之前啟動新事務:對于剛開始于批量操作的新事務,此操作完成后,更新/刪除將在數據庫中執行。 您將沒有實體管理器嘗試使用尚未寫入數據庫的數據。
- 在批量操作之前調用“ entityManager.clear()”方法:如果調用此方法,則將強制“持久性上下文”釋放所有緩存的數據。 批量操作后,如果您使用find方法,則持久性上下文將從數據庫中獲取數據,因為您在批量操作之前清除了緩存的數據。
調用clear()方法不是靈丹妙藥,如果多次使用它會給您帶來性能問題。 如果您的Persistence Context有很多緩存的對象,并且您調用clear()方法,則Persistence Context將必須執行很多“行程”才能再次獲取所需的數據。 持久性上下文具有出色的數據緩存控件,應該利用它。
批量操作是一種可以在多種情況下為我們提供幫助的選項, 但是您必須謹慎使用它。
JPA:條件
JPA是運行查詢的一個很好的框架,但是Criteria并不是使用JPA進行查詢的一個好方法。
JPA標準過于冗長,復雜,并且需要太多代碼才能進行一些基本查詢。 不幸的是,作為休眠標準并不容易。
下面的代碼將顯示一個簡單的Criteria代碼,但我們不會再看到更多有關此主題的信息。 我已經讀了三本關于EJB / JPA的書,而沒有一本書談論它。
下面的代碼有一個標準代碼:
package com.main;import java.util.List;import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaQuery;import com.model.Person;public class Page15 {@SuppressWarnings({ 'unchecked', 'rawtypes' })public static void main(String[] args) {CodeGenerator.startConnection();CodeGenerator.generateData();EntityManager em = CodeGenerator.getEntityManager();CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery();criteriaQuery.select(criteriaQuery.from(Person.class));List<Person> result = em.createQuery(criteriaQuery).getResultList();System.out.println('Found ' + result.size() + ' persons.');CodeGenerator.closeConnection();}
}
我很遺憾在這里這樣說我對Criteria的看法,但是到目前為止,除非對于ListALL,否則在您的代碼中使用Criteria并不容易。
上面的代碼很容易應用于通用DAO,因此通過它列出所有對象會更容易。
以下鏈接顯示了應用程序中的通用DAO: 完整WebApplication JSF EJB JPA JAAS 。
結束!
希望這篇文章對您有所幫助。
單擊此處下載源代碼。
您無需編輯任何配置即可運行本文的代碼,只需將其導入Eclipse。
如果您有任何疑問/意見,請在下面將其發布。
再見。
有用的鏈接:
- http://www.mkyong.com/hibernate/how-to-display-hibernate-sql-parameter-values-log4j/
- http://stackoverflow.com/questions/1659030/how-to-get-the-database-time-with-jpql
- Pro EJB 3:Java持久性API,Mike Keith,Merrick Schincariol
- 企業JavaBeans 3.0 – Richard Monson-Haefel,Bill Burke
參考: uaiHebert博客上來自JCG合作伙伴 Hebert Coelho的JPA查詢和技巧 。
翻譯自: https://www.javacodegeeks.com/2012/07/ultimate-jpa-queries-and-tips-list-part_7092.html