關(guān)于使用jpa聚合函數(shù)遇到的問(wèn)題
使用jpa聚合函數(shù)遇到的問(wèn)題
spring data jpa 可以通過(guò)在接口中按照規(guī)定語(yǔ)法創(chuàng)建一個(gè)方法進(jìn)行增刪改查,可以快速開(kāi)發(fā)。
但是一些特殊情況,如按條件查詢(xún)統(tǒng)計(jì),這個(gè)時(shí)候通過(guò)規(guī)定語(yǔ)法還是直接@Query寫(xiě)原生sql都不能解決,因?yàn)檫@個(gè)統(tǒng)計(jì)的條件不好添加。
百度之后,可以使用EntityManager來(lái)解決。
EntityManager 對(duì)象在一組實(shí)體類(lèi)與底層數(shù)據(jù)源之間進(jìn)行 O/R 映射的管理。它可以用來(lái)管理和更新 Entity Bean, 根椐主鍵查找 Entity Bean, 還可以通過(guò)JPQL語(yǔ)句增刪改查實(shí)體。
首先通過(guò)@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條件后面是對(duì)象信息,不能直接傳入對(duì)象拼成sql,會(huì)報(bào)錯(cuò). ? ? sql.append(" AND customer = :customer"); } Query query = em.createQuery(sql.toString()); if (order.getCustomer() != null) { ? ? //通過(guò)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)合查詢(xún))
最近幫老同事解決一個(gè)問(wèn)題,場(chǎng)景是這樣的,查詢(xún)條件比較多,也就是我們說(shuō)的聯(lián)合查詢(xún),比如下面的,時(shí)間可以選不同的,狀態(tài)和來(lái)源也可以選不同,而且可選可不選
如果這個(gè)時(shí)候?qū)憇ql,是不是要各種條件判斷,各種糾結(jié),各種難寫(xiě),各種sql,這個(gè)時(shí)候大家一般都想到了springdata的jpa貌似很好用,可以直接拼接sql,但是怎么拼接呢,又怎么支持非表字段的展示呢,比如表中一個(gè)字段 aaa 好展示,但是查總和sum(aaa) ,怎么把這個(gè)作為一個(gè)字段展示呢。
不羅嗦了,直接上代碼
以下語(yǔ)句對(duì)應(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是對(duì)應(yīng)數(shù)據(jù)庫(kù)的類(lèi)名,替換成自己的 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);//獲取時(shí)間的方法,具體代碼我就不沾了,自己寫(xiě)個(gè)就行了 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; }
這個(gè)sql,我們分別查到了兩個(gè)值 status 和數(shù)量,那么怎么獲取呢
循環(huán)一下那個(gè)獲取的list
Tuple tuple = list.get(i); (long)tuple.get(0)獲取的是數(shù)量 (Integer)tuple.get(1)獲取的是狀態(tài)id
到這是否全部清晰了呢,這個(gè)例子也適用sum,max等其他聚合函數(shù)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java?Elastic-Job分布式定時(shí)任務(wù)使用方法介紹
xxl-job?通過(guò)一個(gè)中心式的調(diào)度平臺(tái),調(diào)度多個(gè)執(zhí)行器執(zhí)行任務(wù),調(diào)度中心通過(guò)?DB?鎖保證集群分布式調(diào)度的一致性,這樣擴(kuò)展執(zhí)行器會(huì)增大?DB?的壓力,然而大部分公司的任務(wù)數(shù),執(zhí)行器并不多;xxl-job?提供了非常好用的監(jiān)控頁(yè)面甚至還有任務(wù)失敗的郵件告警功能2023-01-01獲取Java加載器和類(lèi)完整結(jié)構(gòu)的方法分享
這篇文章主要為大家詳細(xì)介紹了獲取Java加載器和類(lèi)完整結(jié)構(gòu)的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-12-12使用spring框架中的組件發(fā)送郵件功能說(shuō)明
Spring使用的是基本的JavaBean來(lái)完成以前只可能由EJB完成的事情。這篇文章主要介紹了使用spring框架中的組件發(fā)送郵件,需要的朋友可以參考下2017-11-11JavaWeb?Servlet實(shí)現(xiàn)文件上傳與下載功能實(shí)例
因自己負(fù)責(zé)的項(xiàng)目中需要實(shí)現(xiàn)文件上傳,所以下面下面這篇文章主要給大家介紹了關(guān)于JavaWeb?Servlet實(shí)現(xiàn)文件上傳與下載功能的相關(guān)資料,需要的朋友可以參考下2022-04-04關(guān)于使用swagger整合springMVC的方法
在平時(shí)開(kāi)發(fā)寫(xiě)接口文檔的工作時(shí),一般都是word文檔,帶來(lái)書(shū)寫(xiě)麻煩、維護(hù)麻煩的問(wèn)題,比如改了源代碼忘了更新文檔、解釋不明確帶來(lái)歧義、無(wú)法在線(xiàn)嘗試等等,swagger可以有效解決這類(lèi)問(wèn)題,需要的朋友可以參考下2023-04-04JAVA實(shí)現(xiàn)監(jiān)測(cè)tomcat是否宕機(jī)及控制重啟的方法
這篇文章主要介紹了JAVA實(shí)現(xiàn)監(jiān)測(cè)tomcat是否宕機(jī)及控制重啟的方法,可實(shí)現(xiàn)有效的檢測(cè)及控制tomcat服務(wù)器運(yùn)行,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08linux部署出現(xiàn)java文件操作報(bào)錯(cuò):java.io.FileNotFoundException解決辦法
這篇文章主要g介紹了linux部署出現(xiàn)java文件操作報(bào)錯(cuò):java.io.FileNotFoundException解決的相關(guān)資料,這個(gè)錯(cuò)誤通常表示你的Spring Boot應(yīng)用程序無(wú)法找到指定的文本文件,需要的朋友可以參考下2023-12-12JDBC獲取數(shù)據(jù)庫(kù)連接的5種方式實(shí)例
JDBC是一種用于執(zhí)行SQL語(yǔ)句的JavaAPI,為多種關(guān)系數(shù)據(jù)庫(kù)提供統(tǒng)一訪(fǎng)問(wèn),它由一組用Java語(yǔ)言編寫(xiě)的類(lèi)和接口組成,提供了諸如查詢(xún)和更新數(shù)據(jù)庫(kù)中數(shù)據(jù)的方法,這篇文章主要給大家介紹了關(guān)于JDBC獲取數(shù)據(jù)庫(kù)連接的5種方式,需要的朋友可以參考下2022-06-06