簡體   English   中英

我們是否需要JPA關系和標准API

[英]Do we need JPA Relationships and Criteria API

背景:

我們正在使用傳統的自定義構建查詢生成器,該查詢生成器基本上具有所有與查詢相關的API。 從概念上講,它在某種程度上等同於JPA標准API。 自從我們從EJB 2遷移到EJB 3以來,它對元數據的EJB 2 XML的依賴使我們非常困擾。 問題之一是,僅僅為了查詢生成器,我們不得不維護/更新EJB 2 XML文件。

作為從EJB 2到EJB 3遷移的一部分,我們為所有表創建了Entity類。 但是,我們沒有在實體之間添加關系。

現在,我們正在尋找擺脫它的方法,並且幾乎我們決定使用JPA。

幾個想法:

鑒於Criteria API要求實體關系,我有以下想法

  1. 實體關系伴隨着決定懶惰或渴望的負擔。 雖然急於加載通常會導致性能問題,但延遲加載會強制使用Open Session In View模式,該模式存在很多問題
  2. 盡管Relationships and Criteria API使開發人員免受數據庫SQL的攻擊,但是在很大程度上由於性能影響的風險遠遠超過了該影響,因為輕微的編程錯誤會導致大量DB sql查詢。 為了避免這種情況,開發人員必須使用數據庫,這使數據庫屏蔽成為一個問題
  3. 截至目前,業務邏輯負責先保留哪個實體。 使用CascadeType將其移動到Entity層似乎沒有任何優勢。
  4. JPQL(NamedQueries和NamedNativeQueries)似乎都與Criteria API一樣強大
  5. 大多數Criteria API資料都聲稱Criteria API在過濾方面是最好的。 但是,在參數數量和表聯接數量更多的情況下,這似乎並不正確。

問題:

也就是說,從廣義上講,實體關系似乎弊大於利。

  1. 使用實體關系的現實情況是什么?
  2. 什么情況下Criteria API勝過JPQL(命名和NamedNative查詢)?

任何想法都非常感謝。

提前致謝,

拉克什

對於此問題,什么方案的Criteria API勝過JPQL(命名和NamedNative查詢)-

我們的項目中有寧靜的Web服務,在這種情況下,我們需要按一些屬性進行過濾。 如果使用查詢方法作為過濾參數的增加,您的查詢也會增加。 在這種情況下,標准api更好。

在下面的示例中,我們有2個查詢參數,因此兩種方法都不錯。 但是,如果您有4或5個過濾查詢參數標准api是最佳選擇。

 public List<AccountEntity> createCriteriaQuery(final List<String> accountIdList,
                final MultiValueMap<String, String> allRequestParams) {

            final EntityManager entityManager = entityManagerFactory.createEntityManager();
            final CriteriaBuilder cb = entityManager.getCriteriaBuilder();

            final CriteriaQuery<AccountEntity> cq = cb.createQuery(AccountEntity.class);
            final Root<AccountEntity> accountEntity = cq.from(AccountEntity.class);

            final Join<AccountEntity, PlanEntity> account = accountEntity.join(AccountEntity_.planEntity);

            final List<Predicate> predicates = new ArrayList<Predicate>();
                predicates.add(accountEntity.get(AccountEntity_.id).in(accountIdList));

            if (!allRequestParams.isEmpty()) {
                if (allRequestParams.containsKey(ApplicationConstants.QUERYPARAM_ACCOUNTTYPE)) {
                    String accountType = allRequestParams.get(ApplicationConstants.QUERYPARAM_ACCOUNTTYPE).get(0);
                    if (accountType.equalsIgnoreCase(ApplicationConstants.ACCOUNTTYPE_POINT)) {
                        accountType = ApplicationConstants.ACCOUNTTYPE_PTS;
                    }
                    predicates.add(cb.equal(accountEntity.get(AccountEntity_.accounttype), accountType));
                }

                if (allRequestParams.containsKey(ApplicationConstants.QUERYPARAM_PLANNAME)) {
                    final String planName = allRequestParams.get(ApplicationConstants.QUERYPARAM_PLANNAME).get(0);

                    predicates.add(cb.like(account.get(PlanEntity_.name), "%" + planName + "%"));
                }
            }
            cq.select(accountEntity).where(predicates.toArray(new Predicate[] {}));
            cq.orderBy(cb.asc(account.get(PlanEntity_.name)));
            final TypedQuery<AccountEntity> qry = entityManager.createQuery(cq);

            return qry.getResultList();
        }

實體關系伴隨着決定懶惰或渴望的負擔。 雖然急於加載通常會導致性能問題,但延遲加載會強制使用Open Session In View模式,該模式存在很多問題

您可能使JPA變得比所需的復雜。 實體是通過例外配置的,因此在很多時候,明智的默認值會應用於您的關系中(例如,懶惰一對多,渴望一對一)。 如果您的概要分析確定了與實體加載相關的性能問題,則只需指定急切或延遲映射。

特別是,如果關系經常被頻繁加載,則惰性映射會導致性能問題,這將導致額外的數據庫訪問。 如果不使用這種關系,則渴望映射可能會類似地導致性能問題。 這些是訪問高度規范化數據時始終存在的問題,而不僅僅是JPA的問題。

盡管Relationships and Criteria API使開發人員免受數據庫SQL的攻擊,但是在很大程度上由於性能影響的風險遠遠超過了該影響,因為輕微的編程錯誤會導致大量DB sql查詢。 為了避免這種情況,開發人員必須使用數據庫,這使數據庫屏蔽成為一個問題

我認為,JPA的風險收益比被誇大了。 雖然有時可以通過使用自己的JDBC調用來獲得更好的性能,但是通常會誇大了性能優勢,因此必須相對於ORM的其他優勢進行權衡。 我傾向於認為“ ORM是您的朋友”。

正如預期的那樣,業務邏輯會照顧哪個實體先於另一個實體存在。 使用CascadeType將其移動到Entity層似乎沒有任何優勢。

級聯是一個選項,您可以在操作鏈接與關系類型密切相關的適當實體中指定。 沒有人時就沒有優勢。

JPQL(NamedQueries和NamedNativeQueries)似乎都與Criteria API一樣強大

它們只是可以用來完成同一件事的不同范例。 Criteria API是一種簡單的DSL,允許您通過使用方法調用構建一系列Java對象來對實體對象構造查詢。 JPQL查詢是使用字符串構建的。

大多數Criteria API資料都聲稱Criteria API在過濾方面是最好的。 但是,在參數數量和表聯接數量更多的情況下,這似乎並不正確。

JPQL和Criteria API是完成同一件事的不同方式。 它們是比沖突更具互補性的技術。

  1. 實體關系將使您不必再單獨調用存儲庫,而這會在延遲加載時自動發生。 同樣,您也不希望將實體對象傳遞給Controller,因為它們將能夠在業務邏輯之外修改您的實體。 您想給他們數據,而不是給數據庫的連接。 而且,如果這樣做,則無需在控制器中打開會話。

  2. 使用NamedQueries和Criteria,您真的想在NamedQueries無法使用時使用Criteria,即,當您有一個確定的謂詞時,請使用NamedQuery。 但是,如果您的謂詞不固定,例如,當訂單類型為貨到付款時,您在查詢中添加了價格限制,則必須通過條件。

說了這么多,恕我直言,避免使用標准和關系讓您容易出錯的想法是有缺陷的。 無論如何,您在SQL上都可能遇到相同的錯誤,這就是測試的全部目的。

級聯是一種在某些情況下有效的想法,但不一定在所有情況下都有用。 如果您想明確地級聯,那沒什么大不了的。

暫無
暫無

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

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