1.46 增加通用统计查询方法,子类直接实现即可。
This commit is contained in:
parent
23f4daf3e9
commit
16a7b9513d
@ -7,7 +7,6 @@ import com.qqchen.deploy.backend.deploy.query.ApplicationQuery;
|
||||
import com.qqchen.deploy.backend.deploy.service.IApplicationService;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.framework.controller.BaseController;
|
||||
import com.qqchen.deploy.backend.framework.dto.PageResult;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@ -54,11 +53,6 @@ public class ApplicationApiController extends BaseController<Application, Applic
|
||||
return super.findAll();
|
||||
}
|
||||
|
||||
@GetMapping("/pageWithStats")
|
||||
public Response<PageResult<ApplicationDTO>> pageWithStats(ApplicationQuery query) {
|
||||
return Response.success(applicationService.pageWithStats(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<List<ApplicationDTO>> findAll(ApplicationQuery query) {
|
||||
return super.findAll(query);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.deploy.query;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum;
|
||||
import com.qqchen.deploy.backend.framework.annotation.QueryField;
|
||||
import com.qqchen.deploy.backend.framework.enums.QueryType;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
@ -28,8 +29,8 @@ public class ApplicationQuery extends BaseQuery {
|
||||
@QueryField(field = "buildType")
|
||||
private String buildType;
|
||||
|
||||
@QueryField(field = "languageType")
|
||||
private String languageType;
|
||||
@QueryField(field = "language")
|
||||
private DevelopmentLanguageTypeEnum language;
|
||||
|
||||
@QueryField(field = "applicationCategoryId")
|
||||
private Long applicationCategoryId;
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
package com.qqchen.deploy.backend.deploy.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.entity.Application;
|
||||
import com.qqchen.deploy.backend.deploy.repository.projection.ApplicationEnabledStatistics;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface IApplicationRepository extends IBaseRepository<Application, Long> {
|
||||
|
||||
@ -16,15 +12,4 @@ public interface IApplicationRepository extends IBaseRepository<Application, Lon
|
||||
*/
|
||||
Long countByApplicationCategoryIdAndDeletedFalse(Long applicationCategoryId);
|
||||
|
||||
/**
|
||||
* 按启用状态分组统计应用数量(一次查询获取已启用和已禁用的数量)
|
||||
*
|
||||
* @return 统计结果列表,包含enabled状态和对应的count
|
||||
*/
|
||||
@Query("SELECT a.enabled as enabled, COUNT(a) as count " +
|
||||
"FROM Application a " +
|
||||
"WHERE a.deleted = false " +
|
||||
"GROUP BY a.enabled")
|
||||
List<ApplicationEnabledStatistics> countByEnabledGroupBy();
|
||||
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package com.qqchen.deploy.backend.deploy.repository.projection;
|
||||
|
||||
/**
|
||||
* 应用启用状态统计投影接口
|
||||
* 用于Spring Data JPA的查询结果映射
|
||||
*/
|
||||
public interface ApplicationEnabledStatistics {
|
||||
|
||||
/**
|
||||
* 获取启用状态
|
||||
* @return true=已启用,false=已禁用
|
||||
*/
|
||||
Boolean getEnabled();
|
||||
|
||||
/**
|
||||
* 获取该状态下的应用数量
|
||||
* @return 应用数量
|
||||
*/
|
||||
Long getCount();
|
||||
}
|
||||
@ -4,21 +4,12 @@ import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO;
|
||||
import com.qqchen.deploy.backend.deploy.dto.DevelopmentLanguageTypeDTO;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Application;
|
||||
import com.qqchen.deploy.backend.deploy.query.ApplicationQuery;
|
||||
import com.qqchen.deploy.backend.framework.dto.PageResult;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IApplicationService extends IBaseService<Application, ApplicationDTO, ApplicationQuery, Long> {
|
||||
|
||||
/**
|
||||
* 分页查询应用(带统计信息)
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return 分页结果,包含已启用和已禁用的总数统计
|
||||
*/
|
||||
PageResult<ApplicationDTO> pageWithStats(ApplicationQuery query);
|
||||
|
||||
List<DevelopmentLanguageTypeDTO> getAllDevelopmentLanguageTypes();
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.qqchen.deploy.backend.system.model.ExternalSystemDTO;
|
||||
import com.qqchen.deploy.backend.deploy.entity.Application;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ApplicationCategory;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
import com.qqchen.deploy.backend.deploy.entity.QApplication;
|
||||
import com.qqchen.deploy.backend.deploy.entity.RepositoryProject;
|
||||
import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum;
|
||||
import com.qqchen.deploy.backend.deploy.query.ApplicationQuery;
|
||||
@ -19,23 +20,21 @@ import com.qqchen.deploy.backend.deploy.repository.IApplicationRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IRepositoryProjectRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.ITeamApplicationRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.projection.ApplicationEnabledStatistics;
|
||||
import com.qqchen.deploy.backend.deploy.service.IApplicationService;
|
||||
import com.qqchen.deploy.backend.framework.dto.PageResult;
|
||||
import com.qqchen.deploy.backend.framework.dto.PageStats;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import org.springframework.data.domain.Page;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@ -111,36 +110,27 @@ public class ApplicationServiceImpl extends BaseServiceImpl<Application, Applica
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加启用/禁用统计信息
|
||||
*/
|
||||
@Override
|
||||
public PageResult<ApplicationDTO> pageWithStats(ApplicationQuery query) {
|
||||
Page<ApplicationDTO> page = super.page(query);
|
||||
fillApplicationRelations(page.getContent());
|
||||
protected void addStats(PageStats<ApplicationDTO> result, ApplicationQuery query) {
|
||||
// 复用框架的查询条件构建
|
||||
BooleanBuilder predicate = createQueryPredicate(query);
|
||||
|
||||
// 一次查询获取启用和禁用状态的应用总数(按enabled分组统计)
|
||||
List<ApplicationEnabledStatistics> statistics = applicationRepository.countByEnabledGroupBy();
|
||||
// 统计启用和禁用数量(带筛选条件)
|
||||
Long enabledCount = applicationRepository.count(predicate.and(QApplication.application.enabled.eq(true)));
|
||||
Long disabledCount = applicationRepository.count(predicate.and(QApplication.application.enabled.eq(false)));
|
||||
|
||||
// 解析统计结果
|
||||
Long enabledCount = 0L;
|
||||
Long disabledCount = 0L;
|
||||
for (ApplicationEnabledStatistics stat : statistics) {
|
||||
if (Boolean.TRUE.equals(stat.getEnabled())) {
|
||||
enabledCount = stat.getCount();
|
||||
} else if (Boolean.FALSE.equals(stat.getEnabled())) {
|
||||
disabledCount = stat.getCount();
|
||||
}
|
||||
}
|
||||
|
||||
// 构建PageResult并添加统计字段
|
||||
return new PageResult<>(page)
|
||||
.addExtraField("enabledCount", enabledCount)
|
||||
.addExtraField("disabledCount", disabledCount);
|
||||
result.addStat("enabledCount", enabledCount);
|
||||
result.addStat("disabledCount", disabledCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ApplicationDTO> page(ApplicationQuery query) {
|
||||
Page<ApplicationDTO> page = super.page(query);
|
||||
fillApplicationRelations(page.getContent());
|
||||
return page;
|
||||
Page<ApplicationDTO> result = super.page(query);
|
||||
fillApplicationRelations(result.getContent());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,12 +2,12 @@ package com.qqchen.deploy.backend.framework.controller;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import org.springframework.data.domain.Page;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@ -15,225 +15,136 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 通用分页结果包装类
|
||||
* 带统计信息的分页结果包装类
|
||||
* 实现Page接口,保留Spring Data Page的所有字段,并支持添加额外的统计字段
|
||||
* 额外字段会通过@JsonAnyGetter展开到与totalElements同一层级
|
||||
*
|
||||
* @param <T> 分页数据类型
|
||||
*/
|
||||
public class PageResult<T> implements Page<T>, Serializable {
|
||||
public class PageStats<T> implements Page<T>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 内部Page对象,用于委托所有Page接口方法
|
||||
*/
|
||||
@JsonIgnore
|
||||
private final Page<T> page;
|
||||
|
||||
/**
|
||||
* 额外的统计字段,会被展开到JSON的顶层
|
||||
*/
|
||||
@JsonIgnore
|
||||
private final Map<String, Object> extraFields = new HashMap<>();
|
||||
private final Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param page Spring Data Page对象
|
||||
*/
|
||||
public PageResult(Page<T> page) {
|
||||
public PageStats(Page<T> page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加额外的统计字段
|
||||
*
|
||||
* @param key 字段名
|
||||
* @param value 字段值
|
||||
* @return 当前对象(支持链式调用)
|
||||
* 添加统计字段
|
||||
*/
|
||||
public PageResult<T> addExtraField(String key, Object value) {
|
||||
this.extraFields.put(key, value);
|
||||
public PageStats<T> addStat(String key, Object value) {
|
||||
this.stats.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jackson注解:将extraFields的内容展开到JSON的顶层
|
||||
* 使得额外字段与totalElements等在同一层级
|
||||
*/
|
||||
@JsonAnyGetter
|
||||
public Map<String, Object> getExtraFields() {
|
||||
return extraFields;
|
||||
public Map<String, Object> getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jackson注解:支持反序列化时设置额外字段
|
||||
*/
|
||||
@JsonAnySetter
|
||||
public void setExtraField(String key, Object value) {
|
||||
extraFields.put(key, value);
|
||||
public void setStat(String key, Object value) {
|
||||
stats.put(key, value);
|
||||
}
|
||||
|
||||
// ==================== 实现Page接口的所有方法 ====================
|
||||
// ==================== 实现Page接口 ====================
|
||||
|
||||
/**
|
||||
* 获取当前页的数据列表
|
||||
*/
|
||||
@Override
|
||||
public List<T> getContent() {
|
||||
return page.getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总记录数
|
||||
*/
|
||||
@Override
|
||||
public long getTotalElements() {
|
||||
return page.getTotalElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总页数
|
||||
*/
|
||||
@Override
|
||||
public int getTotalPages() {
|
||||
return page.getTotalPages();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前页码(从0开始)
|
||||
*/
|
||||
@Override
|
||||
public int getNumber() {
|
||||
return page.getNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每页大小
|
||||
*/
|
||||
@Override
|
||||
public int getSize() {
|
||||
return page.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前页的实际记录数
|
||||
*/
|
||||
@Override
|
||||
public int getNumberOfElements() {
|
||||
return page.getNumberOfElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有内容
|
||||
*/
|
||||
@Override
|
||||
public boolean hasContent() {
|
||||
return page.hasContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return page.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为第一页
|
||||
*/
|
||||
@Override
|
||||
public boolean isFirst() {
|
||||
return page.isFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为最后一页
|
||||
*/
|
||||
@Override
|
||||
public boolean isLast() {
|
||||
return page.isLast();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有下一页
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return page.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有上一页
|
||||
*/
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return page.hasPrevious();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排序信息
|
||||
*/
|
||||
@Override
|
||||
public Sort getSort() {
|
||||
return page.getSort();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分页信息
|
||||
*/
|
||||
@Override
|
||||
public Pageable getPageable() {
|
||||
return page.getPageable();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一页的分页信息
|
||||
*/
|
||||
@Override
|
||||
public Pageable nextPageable() {
|
||||
return page.nextPageable();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上一页的分页信息
|
||||
*/
|
||||
@Override
|
||||
public Pageable previousPageable() {
|
||||
return page.previousPageable();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换当前页的数据类型
|
||||
*
|
||||
* @param converter 转换函数
|
||||
* @param <U> 目标类型
|
||||
* @return 新的PageResult对象
|
||||
*/
|
||||
@Override
|
||||
public <U> PageResult<U> map(Function<? super T, ? extends U> converter) {
|
||||
public <U> PageStats<U> map(Function<? super T, ? extends U> converter) {
|
||||
Page<U> mappedPage = page.map(converter);
|
||||
PageResult<U> result = new PageResult<>(mappedPage);
|
||||
// 复制额外字段
|
||||
result.extraFields.putAll(this.extraFields);
|
||||
PageStats<U> result = new PageStats<>(mappedPage);
|
||||
result.stats.putAll(this.stats);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取迭代器
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return page.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内部Page对象(用于需要直接访问Page的场景)
|
||||
*/
|
||||
@JsonIgnore
|
||||
public Page<T> getPage() {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,8 @@ package com.qqchen.deploy.backend.framework.service;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import org.springframework.data.domain.Page;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@ -11,6 +11,7 @@ import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import com.qqchen.deploy.backend.framework.dto.PageStats;
|
||||
import com.qqchen.deploy.backend.framework.enums.QueryType;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.query.DateRange;
|
||||
@ -131,7 +132,18 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, Q
|
||||
public Page<D> page(Q query) {
|
||||
validateDatabaseOperation("page");
|
||||
Page<T> page = repository.findAll(createQueryPredicate(query), createPageRequest(query));
|
||||
return converter.toDtoPage(page);
|
||||
Page<D> dtoPage = converter.toDtoPage(page);
|
||||
PageStats<D> result = new PageStats<>(dtoPage);
|
||||
addStats(result, query);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加统计信息钩子方法
|
||||
* 子类可重写此方法添加自定义统计字段
|
||||
*/
|
||||
protected void addStats(PageStats<D> result, Q query) {
|
||||
// 默认空实现,子类可重写
|
||||
}
|
||||
|
||||
protected BooleanBuilder createQueryPredicate(BaseQuery query) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user