關(guān)于使用jpa聚合函數(shù)遇到的問題
使用jpa聚合函數(shù)遇到的問題
spring data jpa 可以通過在接口中按照規(guī)定語法創(chuàng)建一個方法進行增刪改查,可以快速開發(fā)。
但是一些特殊情況,如按條件查詢統(tǒng)計,這個時候通過規(guī)定語法還是直接@Query寫原生sql都不能解決,因為這個統(tǒng)計的條件不好添加。
百度之后,可以使用EntityManager來解決。
EntityManager 對象在一組實體類與底層數(shù)據(jù)源之間進行 O/R 映射的管理。它可以用來管理和更新 Entity Bean, 根椐主鍵查找 Entity Bean, 還可以通過JPQL語句增刪改查實體。
首先通過@PersistenceContext注入EntityManager
@PersistenceContext private EntityManager em;
使用如下
BigDecimal totals = new BigDecimal(0);
StringBuffer sql= new StringBuffer("SELECT SUM(total) FROM Order WHERE state = 1");
if (StringUtils.isNotBlank(order.getOrderNo())) {
? ? sql.append(" AND orderNo = ").append(order.getOrderNo());
}
if (StringUtils.isNotBlank(orderTime)) {
? ? sql.append(" AND orderPayTime LIKE '").append(orderTime).append("%'");
}
if (order.getCustomer() != null) {
? ? //where條件后面是對象信息,不能直接傳入對象拼成sql,會報錯.
? ? sql.append(" AND customer = :customer");
}
Query query = em.createQuery(sql.toString());
if (order.getCustomer() != null) {
? ? //通過setParameter,給參數(shù)賦值.
? ? query.setParameter("customer", order.getCustomer());
}
Object result = query.getSingleResult();
if (result != null) {
? ? totals = new BigDecimal(result.toString());
}
return totals;jpa聚合函數(shù)(適用于聯(lián)合查詢)
最近幫老同事解決一個問題,場景是這樣的,查詢條件比較多,也就是我們說的聯(lián)合查詢,比如下面的,時間可以選不同的,狀態(tài)和來源也可以選不同,而且可選可不選

如果這個時候?qū)憇ql,是不是要各種條件判斷,各種糾結(jié),各種難寫,各種sql,這個時候大家一般都想到了springdata的jpa貌似很好用,可以直接拼接sql,但是怎么拼接呢,又怎么支持非表字段的展示呢,比如表中一個字段 aaa 好展示,但是查總和sum(aaa) ,怎么把這個作為一個字段展示呢。
不羅嗦了,直接上代碼
以下語句對應(yīng)的sql大概是
select count(***) from *** where *** group by ***
private List<Tuple> getCountByStatusOrSource(Integer status, Integer source, Integer userId, String startTime, String endTime, Integer timeSlot, String type) throws Exception {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
Date sTime = new Date(), eTime = new Date();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<AAA> root = query.from(AAA.class);//AAA是對應(yīng)數(shù)據(jù)庫的類名,替換成自己的
Path<Integer> statusPath = root.get("status");
Path<String> statusNamePath = root.get("status").get("name");
Path<Integer> sourcePath = root.get("source");
Path<Date> operatorPath = root.get("operator");
List<Predicate> predicateList = new ArrayList<>();
if (source != null) {
predicateList.add(
cb.equal(sourcePath, source)
);
}
if (userId != null) {
predicateList.add(
cb.equal(operatorPath, userId)
);
}
Map timeMap = getChangedTime(startTime, endTime, timeSlot);//獲取時間的方法,具體代碼我就不沾了,自己寫個就行了
sTime = (Date) timeMap.get("sTime");
eTime = (Date) timeMap.get("eTime");
Expression<Date> startDateExpression = cb.literal(sTime);
Expression<Date> endDateExpression = cb.literal(eTime);
predicateList.add(
cb.between(updateTimePath, startDateExpression, endDateExpression)
);
Predicate[] predicates = new Predicate[predicateList.size()];
predicates = predicateList.toArray(predicates);
query.where(predicates);//where條件加上
if ("status".equals(type)) {
query.select(cb.tuple(statusPath, cb.count(root)));
query.groupBy(statusPath);
}
//query.multiselect(statusPath, cb.count(root));//
TypedQuery<Tuple> q = entityManager.createQuery(query);
List<Tuple> result = q.getResultList();
return result;
}這個sql,我們分別查到了兩個值 status 和數(shù)量,那么怎么獲取呢
循環(huán)一下那個獲取的list
Tuple tuple = list.get(i); (long)tuple.get(0)獲取的是數(shù)量 (Integer)tuple.get(1)獲取的是狀態(tài)id
到這是否全部清晰了呢,這個例子也適用sum,max等其他聚合函數(shù)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
idea使用spring Initializr 快速搭建springboot項目遇到的坑
這篇文章主要介紹了idea使用spring Initializr 快速搭建springboot項目遇到的坑,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
詳解Java中使用externds關(guān)鍵字繼承類的用法
子類使用extends繼承父類是Java面向?qū)ο缶幊讨械幕A(chǔ)知識,這里我們就來詳解Java中使用externds關(guān)鍵字繼承類的用法,需要的朋友可以參考下2016-07-07
springboot @RequiredArgsConstructor的概念與使用方式
這篇文章主要介紹了springboot @RequiredArgsConstructor的概念與使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-09-09
SpringBoot中使用?ThreadLocal?進行多線程上下文管理及注意事項小結(jié)
本文詳細介紹了ThreadLocal的原理、使用場景和示例代碼,并在SpringBoot中使用ThreadLocal保存請求中攜帶的用戶信息,ThreadLocal通過為每個線程維護獨立的變量副本,解決了線程安全問題,感興趣的朋友一起看看吧2025-02-02
如何在Spring中使用編碼方式動態(tài)配置Bean詳解
這篇文章主要給大家介紹了關(guān)于如何在Spring中使用編碼方式動態(tài)配置Bean的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05
springboot接收json數(shù)據(jù)時,接收到空值問題
這篇文章主要介紹了springboot接收json數(shù)據(jù)時,接收到空值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
解決feign接口返回泛型設(shè)置屬性為null的問題
這篇文章主要介紹了解決feign接口返回泛型設(shè)置屬性為null的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

