无锡网站制作怎么样,做网站优化哪家好,重庆网站制作的网站,温州公司做网站目录 前言示例简单示例只查询部分字段#xff0c;映射到一个实体类中只查询部分字段时#xff0c;也可以使用ListObject[]接收返回值再复杂一些 前言
在以往写过几篇spring data jpa相关的文章#xff0c;分别是 Spring Data JPA 使用JpaSpecificationExecutor实现… 目录 前言示例简单示例只查询部分字段映射到一个实体类中只查询部分字段时也可以使用ListObject[]接收返回值再复杂一些 前言
在以往写过几篇spring data jpa相关的文章分别是 Spring Data JPA 使用JpaSpecificationExecutor实现多条件查询分页查询和非分页查询 Spring Data JPA实现分页多条件查询2
都是通过代码而不是sql来完成查询的但是在做复杂情况的查询时难免会用到Query写sql语句。
示例
简单示例
在Query中用:paramName标识参数再用Param来指定方法参数与查询语句中的参数之间的映射关系。 例如
Query(select r from RelationDO r where r.indexCode in :idList)
ListRelationDO findByIdListIn(Param(idList) CollectionString idList);只查询部分字段映射到一个实体类中
注意类的路径写完整
Query(SELECT new com.xxx.service.impl.bo.RecordBO(e.code, e.day, e.total, e.success, e.fail, e.app) FROM RecordDO e WHERE e.code :code AND e.day :day AND e.app in :appCodes)
ListRecordBO findCalendarDetail(Param(code) String code,Param(day) String day,Param(appCodes) ListString appCodes);这里为什么映射了一个新的BO出来呢… 是RecordDO中有一个id字段在实体类中添加了Id注解实体必须有Id不然会报错这个id字段本来设计的是不会重复的但是后续经过一些改动它在某些情况下会重复了这个时候就会有一个问题我直接select整个RecordDOid字段重复的它会当成同一条记录不确定为什么但是实际跑出来确实是这样但我又不想再去改表结构因此这里我select的时候直接省略了id字段就正常了。可能不是一个很好的解决方案但是确实是可以这么做的 只查询部分字段在表字段较多所需字段比较少的时候还是可以用的。
只查询部分字段时也可以使用ListObject[]接收返回值
例如我现在需要用code和month查出这么一个结果
[{day:20240601,result:[{rate: 98.77app: 0001},{rate: 95.32app: 0002}]},{day:20240602,result:[{rate: 95.65app: 0001},{rate: 96.89app: 0002}]},……
]也就是说要把月份中的每一天抽取出来再在下面放每个app对应的明细 这个时候写sql
Query(SELECT e.day, e.app, e.success, e.total FROM RecordDO e WHERE e.code :code AND SUBSTRING(e.day, 1, 6) :month AND e.total 0)
ListObject[] findByMonth(Param(code) String code,Param(month) String month);调用上述方法后封装返回数据
ListCalendarBO calendarBOS Lists.newArrayList();
ListObject[] resultList recordRepository.findByMonth(code,month);if (!CollectionUtils.isEmpty(resultList)){for (Object[] result : resultList) {String day (String) result[0];String app (String) result[1];Integer success (Integer) result[2];Integer total (Integer) result[3];double rate (double) success * 100 / total ;double roundedRate Math.round(rate * 100.0) / 100.0;CalendarBO.Result result CalendarBO.Result.builder().app(app).rate(roundedRate).build();// 组装返回内容OptionalCalendarBO optionalBO calendarBOS.stream().filter(bo - bo.getDay().equals(day)).findFirst();// 该日期值不存在则创建 存在则添加不同app的记录if (!optionalBO.isPresent()) {CalendarBO calendarBO CalendarBO.builder().day(day).result(Collections.singletonList(result)).build();calendarBOS.add(calendarBO);}else {CalendarBO calendarBO optionalBO.get();ListCalendarBO.Result results calendarBO.getResult();results.add(result);calendarBO.setAssessResult(results);}}
}再复杂一些
通过beginMonth、endMonth和appCodes筛选需要返回的数据格式如下 这里的pass是有一个标准rate当data中success/totalrate 标准rate时单项视为pass而total中的total则代表该月份区间共统计次数。
{total: [{total: 13,pass: 13,app: 0001},{total: 13,pass: 12,app: 0002}],data: [{code: 101,month: 202406,result: [{total: 13,success: 13,rate: 100,app: 0001},{total: 12,success: 11,rate: 92,app: 0002}]},{code: 102,month: 202406,result: [{total: 15,success: 15,rate: 100,app: 0001}]},……]
}此时的sql:
Query(SELECT e.code, e.app, SUBSTRING(e.day, 1, 6), COUNT(e.statId), SUM(CASE WHEN (CAST(e.success AS double) / e.total) :rate THEN 1 ELSE 0 END) FROM RecordDO e WHERE e.code :code AND SUBSTRING(e.day, 1, 6) BETWEEN :beginMonth AND :endMonth AND ((:appCodes) IS NULL OR e.app IN (:appCodes)) AND e.total 0 GROUP BY e.code, e.app, SUBSTRING(e.day, 1, 6))
ListObject[] findByCodeGroupBy(Param(code) String code,Param(beginMonth) String beginMonth,Param(endMonth) String endMonth,Param(appCodes) ListString appCodes,Param(rate) Double rate);
这样就直接把总数和pass的计数给取出来了statId和总数可以对应 调用上述方法后封装返回数据和之前基本一致
// 根据分类计算总数的映射
MapString, Integer totalCounts new HashMap();
MapString, Integer passCounts new HashMap();
//返回的明细对象
ListDataBO dataList new ArrayList();//假设已获取到code和标准rate的对应关系passRate
for (Map.EntryString, Double entry : passRate.entrySet()) {ListObject[] resultList recordRepository.findByCodeGroupBy(entry.getKey(), reqBO.getBeginMonth(),reqBO.getEndMonth(), reqBO.getAppCodeList(), entry.getValue());if (CollectionUtils.isEmpty(resultList)) {continue;}for (Object[] result : resultList) {String code (String) result[0];String app (String) result[1];String month (String) result[2];Long totalLong (Long) result[3];String total totalLong.toString();Long successLong (Long) result[4];String success successLong.toString();double rateDouble Double.parseDouble(success) / Double.parseDouble(total);String rate String.format(%.2f, rateDouble * 100);DataBO.Result result DataBO.Result.builder().total(total).success(success).rate(rate).app(app).build();//查看dataList中是否该编码和月份的数据已存在 不存在则新建 存在则获取DataBO data dataList.stream().filter(a - a.getCode().equals(code) a.getMonth().equals(month)).findFirst().orElseGet(() - {DataBO newAccount new DataBO();newAccount.setCode(code);newAccount.setMonth(month);accountList.add(newAccount);return newAccount;});if (data.getResult() null) {data.setResult(Lists.newArrayList());}data.getResult().add(result);// 更新统计totalCounts.put(app, totalCounts.getOrDefault(app, 0) Integer.parseInt(total));passCounts.put(app, passCounts.getOrDefault(app, 0) Integer.parseInt(success));}
}
//组装统计类
totalCounts.entrySet().stream().map(entry - {String app entry.getKey();int total entry.getValue();int pass passCounts.getOrDefault(app, 0);TotalCountBO totalCount new TotalCountBO();totalCount.setAppCode(app);totalCount.setTotal(String.valueOf(total));totalCount.setPass(String.valueOf(pass));return totalCount;}).collect(Collectors.toList());return RespBO.builder().data(dataList).total(totalCounts).build();匆忙所写不确定有没有问题有的话联系我~