不知道大家在开发中有没有遇到这种情况,就是要分页返回给前端数据,但是每页展示的数据 类型又是不一样的
如:电商平台的商品瀑布流,可能会有自营和非自营商品的区别,那么每页展示的数据需要一部分为自营商品,一部分为非自营的商品,那这个时候后端要给的数据就需要动些脑子了,这个需求是小编实实在在遇到的需求,当初为了实现在百度和谷歌找了个遍也没找到相关的思路
话不多说,上代码,希望有人能用得到
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 说明: 比率分页请求参数
* </p>
*
* @author Z.jc
* @version 1.0.0
* @since 2020/8/30
*/
@Data
public class RatioPaginationParam implements Serializable {
private static final long serialVersionUID = -1496754980781572809L;
/**
* 总条数
*/
private int allCount;
/**
* 优先总条数 如自营于非自营商品 自营商品优先/或非自营商品优先,自己理清楚
*/
private int priorityCount;
/**
* 优先数据每页展示长度比率 (重点:优先数据比率)
*/
private int ratio;
/**
* 当前页 用户请求当前页
*/
private int current;
/**
* 每页展示 用户请求每页展示
*/
private int pageSize;
}
import lombok.Data;
import java.io.Serializable;
/**
* <p>说明:</p>
*
* @author Z.jc
* @version 1.0.0
* @since 2020/8/30
*/
@Data
public class RatioPagination implements Serializable {
private static final long serialVersionUID = 6722234949377171106L;
/**
* 优先 limit 开始
*/
private int priorityLimitStart;
/**
* 优先limit 长度
*/
private int prioritySize;
/**
* 非优先limit 开始
*/
private int nonPriorityLimitStart;
/**
* 非优先limit 长度
*/
private int nonPrioritySize;
public RatioPagination(int priorityLimitStart,int prioritySize,int nonPriorityLimitStart,int nonPrioritySize){
this.priorityLimitStart = priorityLimitStart;
this.prioritySize = prioritySize;
this.nonPriorityLimitStart = nonPriorityLimitStart;
this.nonPrioritySize = nonPrioritySize;
}
}
/**
* <p>
* 说明: 商品分组工具类
* </p>
*
* @author Z.jc
* @version 1.0.0
* @since 2020/8/30
*/
public class GroupGoodsUtil {
private GroupGoodsUtil(){}
/**
* 数据比对
* @param num1 对比值1
* @param num2 对比值2
* @return 返回结果值 1:num1 gt num2 0:num1 eq num2 -1:num1 lt num2
*/
public static Integer contrast(int num1,int num2){
return Integer.compare(num1, num2);
}
/**
* 计算分页参数
* <p>若使用该方法计算分页参数,请使用limit 查询list 自己封装到pageResult </p>
* @param param 计算分页参数 请求参数
* @return 返回比率分页参数
*/
public static RatioPagination ratioPaginationCalculation(RatioPaginationParam param){
//优先每页展示率算出当前页展示size
int priorityPageSize = Math.toIntExact((long)param.getRatio() * param.getPageSize() / 10000);
//计算优先总页数
int priorityPageCount = (param.getPriorityCount() + priorityPageSize - 1) / priorityPageSize;
//计算非优先总条数
int nonPriorityCount = param.getAllCount() - param.getPriorityCount();
//计算非优先每页展示
int nonPriorityPageSize = param.getPageSize() - priorityPageSize;
//计算非优先总页数
int nonPriorityPageCount = (nonPriorityCount + nonPriorityPageSize - 1)/nonPriorityPageSize;
int contrastResult = contrast(priorityPageCount,nonPriorityPageCount);
int priorityLimitStart = -1;
int prioritySize = -1;
int nonPriorityLimitStart = -1;
int nonPrioritySize = -1;
switch (contrastResult){
//优先页小于非优先页
case -1:
//当前页小于优先页总页数,可进行正常比率查询
if (param.getCurrent() < priorityPageCount) {
//优先每页长度 * 到上一页页书 = 当前页开始index
priorityLimitStart = priorityPageSize * (param.getCurrent() - 1);
prioritySize = priorityPageSize;
nonPriorityLimitStart = nonPriorityPageSize * (param.getCurrent() -1);
nonPrioritySize = nonPriorityPageSize;
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
//当前页大于优先页总页数,代表优先数据已全部展示完毕,当前页不考虑比率,全部取非优先数据
if (param.getCurrent() > priorityPageCount) {
//优先页pageSize * 优先页pageCount - 优先页Count = 优先页末页缺失条数
int priorityLastPageDefect = priorityPageSize * priorityPageCount - param.getPriorityCount();
//优先总页*非优先每页展示量 + 优先页缺失条数 = 优先页结束时非优先已展示数据总量
int priorityEndNonPriorityCount = priorityPageCount * nonPriorityPageSize + priorityLastPageDefect;
//优先分页结束后到当前页上一页非优先的展示总数
int afterEndCount = (param.getCurrent() - 1 - priorityPageCount) * param.getPageSize();
nonPriorityLimitStart = priorityEndNonPriorityCount + afterEndCount;
nonPrioritySize = param.getPageSize();
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
//当前页等于优先页总数 则代表当前页为优先页末页,需要考虑优先数据是否满足比率要求数量,若不满足则用非优先数据补齐
if (param.getCurrent() == priorityPageCount) {
//优先页pageSize * 优先页pageCount - 优先页Count = 优先页末页缺失条数
int priorityLastPageDefect = priorityPageSize * priorityPageCount - param.getPriorityCount();
priorityLimitStart = priorityPageSize * (param.getCurrent() - 1);
prioritySize = priorityPageSize - priorityLastPageDefect;
nonPriorityLimitStart = nonPriorityPageSize * (param.getCurrent() -1);
nonPrioritySize = nonPriorityPageSize + priorityLastPageDefect;
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
throw new CustomException(ResultCode.INVOKE_EXCEPTION,"分页参数计算错误");
case 0:
//优先页等于非优先页 正常返回
priorityLimitStart = priorityPageSize * (param.getCurrent() - 1);
prioritySize = priorityPageSize;
nonPriorityLimitStart = nonPriorityPageSize * (param.getCurrent() -1);
nonPrioritySize = nonPriorityPageSize;
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
case 1:
//优先页大于非优先页 则通过非优先页进行分页参数计算
// 当前页小于非优先页 正常按比率返回
if (param.getCurrent() < nonPriorityPageCount) {
//优先每页长度 * 到上一页页书 = 当前页开始index
priorityLimitStart = priorityPageSize * (param.getCurrent() - 1);
prioritySize = priorityPageSize;
nonPriorityLimitStart = nonPriorityPageSize * (param.getCurrent() -1);
nonPrioritySize = nonPriorityPageSize;
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
//若当前页大于非优先页 则当前页完全返回优先数据 不考虑比率
if (param.getCurrent() > nonPriorityPageCount) {
//非优先页pageSize * 非优先页pageCount - 非优先页Count = 非优先页末页缺失条数
int nonPriorityLastPageDefect = nonPriorityPageSize * nonPriorityPageCount - nonPriorityCount;
//非优先总页*优先每页展示量 + 非优先页缺失条数 = 非优先页结束时优先已展示数据总量
int nonPriorityEndPriorityCount = nonPriorityPageCount * priorityPageSize + nonPriorityLastPageDefect;
//非优先分页结束后到当前页上一页优先的展示总数
int afterEndCount = (param.getCurrent() - 1 - nonPriorityPageCount) * param.getPageSize();
priorityLimitStart = nonPriorityEndPriorityCount + afterEndCount;
prioritySize = param.getPageSize();
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
//若当前页等于非优先页,则考虑非优先数据是否满足比率数量,不满足则用优先商品数据补齐
if (param.getCurrent() == nonPriorityPageCount) {
//优先页pageSize * 优先页pageCount - 优先页Count = 优先页末页缺失条数
int nonPriorityLastPageDefect = nonPriorityPageSize * nonPriorityPageCount - nonPriorityCount;
priorityLimitStart = priorityPageSize * (param.getCurrent() - 1);
prioritySize = priorityPageSize + nonPriorityLastPageDefect;
nonPriorityLimitStart = nonPriorityPageSize * (param.getCurrent() -1);
nonPrioritySize = nonPriorityPageSize - nonPriorityLastPageDefect;
return new RatioPagination(priorityLimitStart,prioritySize,nonPriorityLimitStart,nonPrioritySize);
}
throw new CustomException(ResultCode.INVOKE_EXCEPTION,"分页参数计算错误");
default:
throw new CustomException(ResultCode.INVOKE_EXCEPTION,"分页参数计算错误");
}
}
}
以上就是完整的代码了,通过已知参数,计算出当前页两种类型的数据各自的limit参数,然后进行sql limit查询,就可以得到想要的数据啦
此工具类不仅适用于sql查询,同样适用于redis zset查询