簡體   English   中英

JPA EntityManager:“查找”與“ createQuery”和“ getResultList”

[英]JPA EntityManager: 'find' vs. 'createQuery' and 'getResultList'

我正在使用JPA(不是JPA-2)的舊代碼庫,並且在DAO實現類中遇到了以下方法,以按ID(也是主鍵)檢索單個實體:

public EmailTemplate findEmailTemplateById(long id) {

    LOG.debug("Entering findEmailTemplateById(id='" + id + "')");
    // Construct JPQL query       
    String queryString = "SELECT a FROM EmailTemplate a " +
            "WHERE templateId = :templateId";
    Query query = entityManager.createQuery(queryString);

    query.setParameter("templateId", id);

    LOG.debug("Using query " + queryString);

    List<EmailTemplate> resultList = query.getResultList();

    LOG.debug("Exiting findEmailTemplateByName(id='" + id + "') results size " + resultList.size() + " ( returns null if 0 )");

    if (resultList.isEmpty() || resultList.size() == 0) {
        return null;
    } else {
        return resultList.get(0);
    }

}

現在,我需要為不同的實體編寫類似的DAO類,並且通過主鍵查找實體的方法看起來要簡單得多!

@Override
public EmailTemplateEdit findEmailTemplateEditById(long id) {
    LOG.debug("Entering findEmailTemplateEditById(id={})", id);
    return entityManager.find(EmailTemplateEdit.class, id);
}

原始作者沒有來問這個問題,所以我想知道是否有人可以提出他為何構造JPQL查詢而不是簡單地使用EntityManager#find(Class<T> entityClass, Object primaryKey)

find方法的Javadoc說:

如果實體實例包含在持久性上下文中,則從那里返回它。

這表明某種形式的緩存和/或延遲的寫入。 createQuerygetResultList方法的Javadoc不會這樣說。

我沒有意識到此應用程序中的任何業務或技術要求都將阻止緩存,也沒有意識到由陳舊的實體或類似實體導致的任何問題。 我將與項目團隊的其他成員一起檢查這些情況,但是我只是想以SO社區的意見為依據,查看是否還有其他原因構造和執行查詢而不是簡單地使用find來構建和執行查詢。

(我已經看到了這一點: 當使用EntityManager的createQuery()和find()方法時嗎?雖然它回答了以下問題:createQuery和find之間的區別,但是在通過主鍵查找實體的上下文中它沒有回答)

更新了其他信息

通過查看原始DAO類中的其他方法,似乎已經有一個故意/有意識的決定,不利用JPA管理的對象。 如上所述,按主鍵查找的方法使用JPQL查詢。 刪除實體的方法還使用JPQL查詢。 更新實體的方法將復制傳入的實體對象,並使用該副本調用EntityManager#merge (因此,該副本是托管對象,但從不使用該方法或從該方法返回)
奇怪的 ....

簡短的答案,查找和選擇查詢沒有區別。

您的問題表明您並不完全了解EntityManager和Persistence上下文。 EntityManager實現不需要是線程安全的。 如果EntityManager是由Spring或EJB容器注入的,則它是線程安全的(因為它是線程本地代理),如果它是應用程序管理的(通過調用EntityManagerFactory.createEntityManager()創建的,則不是線程安全的),並且您不能將其存儲在變量中,而每次都必須創建一個新變量。

持久性上下文是實體所在的位置,每當您創建新的EntityManager時,您都會獲得一個新的持久性上下文(此規則有例外)。 當您持久化一個實體,或從數據庫(使用查找或查詢)加載現有實體時,它將由持久性上下文管理。 提交事務時,JPA會在Persistence上下文管理的所有實體中運行,並檢查實體的狀態以找出應將哪些查詢發送到數據庫。

PersistenceContext可以看作是數據庫頂部的一級緩存。 這意味着使用壽命很短,通常不超過交易時間。 如果您將同一entityManager用於多個事務,則大小可能會隨着加載更多數據而增長,這很糟糕,因為每個事務都必須在持久性上下文中遍歷所有實體。

暫無
暫無

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

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