2014-02-17 92 views
2

我試圖得到一個一對多的關係,通過以下關係式所示的總和(僅顯示父):總和與一對多春數據JPA

@Entity 
@Table(name = "Parent") 
public class Parent implements Serializable { 
    private static final long serialVersionUID = -7348332185233715983L; 

    @Id 
    @Basic(optional = false) 
    @Column(name = "PARENT_ID") 
    private Long parentId; 

    @OneToMany 
    @JoinColumn(name="CHILDREN", referencedColumnName="PARENT_ID") 
    private List<Child> children; 

    @Formula("(select sum(select height from children))") 
    private BicDecimal totalHeight 
} 

這是很簡單的,沒有限制甚至是靜態限制。當兒童列表被動態限制時,我遇到了麻煩。

就我而言,我使用的是spring數據和jpa。我正在使用規範來限制孩子,並獲得適當的孩子列表,但顯然這個總數仍然適用於無限制的孩子,因爲@Formula標籤中沒有where子句。

我不想在java中出於性能原因迭代列表,因爲結果是分頁的。此外,總和不是分頁結果,而是所有結果。

我是Spring Data/JPA的新手。從歷史上看,我可以動態構建這個查詢或使用休眠條件。我確定運行完整的單獨查詢來進行此計算。不要求我使用@Formula註釋,因爲每次調用只有1個聚合。在hibernate框架中,我可以將select子句聲明爲「sum(field)」並構建標準。在Spring Data/JPA框架中,我可以建立涵蓋標準的規範,但我不知道如何操作查詢的選擇部分,因爲它似乎與實體緊密相連。

使用的存儲庫中的@Query註釋工作作爲自己的查詢,如果我知道哪些字段我需要限制,但往往這些字段是空的,不需要對查詢被忽略。有8個可能的字段,給我256個可能的組合(2^8)。這在存儲庫中的方法太多了。

轉換框架之外的任何想法?

回答

0

你有沒有在JPQL

select sum(d.height) from Parent a join a.children d 

如果你不想忽略空

select sum(d.height) from Parent a left join a.children d 

我認爲你有其他的問題是如何根據屬性篩選嘗試。我的意思是如果你需要有幾個組合的where語句。

你爲什麼不嘗試使用你想這取決於你想擁有的組合應用列表和添加到列表中的所有謂詞。例如

創建查詢

CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery cq = cb.createQuery(Double.class); 
    Root<Parent> root = cq.from(Parent.class) 
    Join<Parent, Child> join = cq.join(("children")); 
    cq.select(cb.<Double>sum(join.get("height"))); 

創建謂詞的列表

List<Predicates> listOfpredicates = new ArrayList<Predicates>(); 
if(property1 != null && !"".equals(property1){ 
     PatameterExpression<String> p = cb.parameter(String.class, "valueOfproperty1") 
     listOfpredicates.add(cb.equal(join.get("property1"),p); 
} 

然後添加到CriteriaQuery中

if(listOfPredicates.size() == 1) 
    cq.where(listOfPredicates.get(0)) 
else 
    cq.where(cb.and(listOfPredicates.toArray(new Predicate[0]))); 

最後執行查詢。

TypedQuery<Double> q = em.createQuery(cq); 
q.getResultList(); 

這將動態創建您的查詢與任何組合。

0

發佈回答這個老問題,因爲我最近有一個有點類似的問題。

我決定用自定義存儲庫和一個基於任何規範的聚合傳遞給它的方法。規格可以組合構成的動態標準(見org.springframework.data.jpa.domain.Specifications)

所以我的倉庫上面孩子身高問題看起來象下面這樣:

package something 

import org.springframework.data.jpa.domain.Specification; 
import org.springframework.stereotype.Repository; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Root; 

@Repository 
public class ChildHeightRepository { 

    @PersistenceContext 
    EntityManager entityManager; 


    public Long getTotalHeight(Specification<Child> spec) { 

     CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 

     CriteriaQuery query = cb.createQuery(Long.class); 

     Root root = query.from(Child.class); 

     return ((Long) entityManager.createQuery(
       query.where(spec.toPredicate(root, query, cb)) 
         .select(cb.sum(root.get("height")))).getSingleResult()); 


    } 
}