多条件的分页查询
程序员文章站
2024-03-20 19:56:10
...
多条件排序的分页查询
1.前端传递的参数
public class SearchCurrentAlarmQuery {
/**
* 告警名称
**/
private String name;
/**
* 告警源 (组件实例Id)
**/
private Integer componentInstanceId;
/**
* 告警源类型 (组件Id)
**/
private Integer componentId;
/**
* 级别
**/
private List<Integer> levelList;
/**
* 级别
**/
private String levelListStr;
/**
* 告警状态
* 确认状态(已确认1,未确认0)
* 消除状态(已消除1,未消除0)
**/
private List<String> alarmStateList;
/**
* 告警状态
* 确认状态(已确认1,未确认0)
* 消除状态(已消除1,未消除0)
**/
private String alarmStateListStr;
/**
* 最近发生开始时间
**/
private Long latestHappenStartTime;
/**
* 最近发生结束时间
**/
private Long latestHappenEndTime;
/**
* 清除开始时间
**/
private Long handStartTime;
/**
* 清除结束时间
**/
private Long handEndTime;
/**
* 振荡标识(未标识0,标识为振荡1)
**/
private Integer shockMark;
/**
* 排序
* 0:发生时间
* 1:级别
* 2:名称
* 3:告警源(组件实例名称)
* 4:确认状态
* 5:确认时间
* 6:确认人
* 7:清除状态
* 8:清除时间
* 9:定位信息
*
* 最多四个,并且不能重复
* 0:降序
* 1:升序
*
**/
private Map<Integer, Integer> sortMap;
private int pageNum = 1;
private int count = 10;
2.具体的逻辑实现
2.1 service
public HttpResponseTemp<?> searchListByName(SearchCurrentAlarmQuery searchQuery) {
PageHelper.startPage(searchQuery.getPageNum(), searchQuery.getCount());
List<Integer> levelList = searchQuery.getLevelList();
if (CollectionUtil.isNotEmpty(levelList)) {
String levelListStr = CodingUtils.getList2String2(levelList);
searchQuery.setLevelListStr(levelListStr);
}
List<String> alarmStateList = searchQuery.getAlarmStateList();
if (CollectionUtil.isNotEmpty(alarmStateList)) {
String alarmStateListStr = CodingUtils.getList2String3(alarmStateList);
searchQuery.setAlarmStateListStr(alarmStateListStr);
}
List<Alarm> alarmList = alarmBiz.searchListByName(searchQuery);
List<AlarmInfo> alarmInfoList;
if (CollectionUtil.isEmpty(alarmList)) {
alarmInfoList = new ArrayList<>();
} else {
alarmInfoList = alarmList.stream().filter(Objects::nonNull).map(this::convertOfAlarm).collect(Collectors.toList());
this.sortAlarmInfoList(alarmInfoList, searchQuery.getSortMap());
}
PageInfo<Alarm> pageInfo = new PageInfo<>(alarmList);
//PageResult自己定义的类
PageResult pageResult = new PageResult();
pageResult.setTotal(pageInfo.getTotal());
pageResult.setPageNum(searchQuery.getPageNum());
pageResult.setData(alarmInfoList);
return ResultStat.OK.wrap(pageResult, "获取告警分页列表成功");
}
sortAlarmInfoList类
private void sortAlarmInfoList(List<AlarmInfo> alarmInfoList, Map<Integer, Integer> sortMap) {
if (CollectionUtil.isEmpty(sortMap)) {
return;
}
List<String> sortNameList = new ArrayList<>();
List<Boolean> sortTypeList = new ArrayList<>();
sortMap.forEach((key, value) -> {
String name = AlarmSortEnum.getName(key);
if (StringUtils.isNotBlank(name)) {
sortNameList.add(name);
sortTypeList.add(value != 0);
}
});
String[] sortNameArr = sortNameList.toArray(new String[0]);
Boolean[] sortTypeArr = sortTypeList.toArray(new Boolean[0]);
String s = JSONUtil.toJsonStr(alarmInfoList);
logger.info("排序前s:" + s);
if (CollectionUtil.isNotEmpty(sortNameList)) {
ListUtils.sort(alarmInfoList, sortNameArr, sortTypeArr);
}
String s2 = JSONUtil.toJsonStr(alarmInfoList);
logger.info("排序后s2:" + s2);
}
2.2 ListUtils
package org.mye.util;
import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
/**
* @author yinaibang
* 在数据库中查出来的列表中,往往需要对不同的字段重新排序。 一般的做法都是使用排序的字段,重新到数据库中查询。
* 如果不到数据库查询,直接在第一次查出来的list中排序,无疑会提高系统的性能。 下面就写一个通用的方法,对list排序,
*
* 至少需要满足以下5点:
*
* ①.list元素对象类型任意
* ---->使用泛型解决
*
* ②.可以按照list元素对象的任意多个属性进行排序,即可以同时指定多个属性进行排序
* --->使用java的可变参数解决
*
* ③.list元素对象属性的类型可以是数字(byte、short、int、long、float、double等,包括正数、负数、0)、字符串(char、String)、日期(java.util.Date)
* --->对于数字:统一转换为固定长度的字符串解决,比如数字3和123,转换为"003"和"123" ;再比如"-15"和"7"转换为"-015"和"007"
* --->对于日期:可以先把日期转化为long类型的数字,数字的解决方法如上
*
* ④.list元素对象的属性可以没有相应的getter和setter方法
* --->可以使用java反射进行获取private和protected修饰的属性值
*
* ⑤.list元素对象的对象的每个属性都可以指定是升序还是降序
* -->使用2个重写的方法(一个方法满足所有属性都按照升序(降序),另外一个方法满足每个属性都能指定是升序(降序))
*
*
*/
public class ListUtils {
/**
* 对list的元素按照多个属性名称排序,
* list元素的属性可以是数字(byte、short、int、long、float、double等,支持正数、负数、0)、char、String、java.util.Date
*
*
* list元素的属性名称
* @param isAsc
* true升序,false降序
*/
public static <E> void sort(List<E> list, final boolean isAsc, final String... sortnameArr) {
Collections.sort(list, new Comparator<E>() {
public int compare(E a, E b) {
int ret = 0;
try {
for (int i = 0; i < sortnameArr.length; i++) {
ret = ListUtils.compareObject(sortnameArr[i], isAsc, a, b);
if (0 != ret) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
});
}
/**
* 给list的每个属性都指定是升序还是降序
*
* @param list
* @param sortnameArr 参数数组
* @param typeArr 每个属性对应的升降序数组, true升序,false降序
*/
public static <E> void sort(List<E> list, final String[] sortnameArr, final Boolean[] typeArr) {
if (sortnameArr.length != typeArr.length) {
throw new RuntimeException("属性数组元素个数和升降序数组元素个数不相等");
}
Collections.sort(list, new Comparator<E>() {
public int compare(E a, E b) {
int ret = 0;
try {
for (int i = 0; i < sortnameArr.length; i++) {
ret = ListUtils.compareObject(sortnameArr[i], typeArr[i], a, b);
if (0 != ret) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
});
}
/**
* 对2个对象按照指定属性名称进行排序
*
* @param sortname
* 属性名称
* @param isAsc
* true升序,false降序
* @param a
* @param b
* @return
* @throws Exception
*/
private static <E> int compareObject(final String sortname, final boolean isAsc, E a, E b) throws Exception {
int ret;
Object value1 = ListUtils.forceGetFieldValue(a, sortname);
Object value2 = ListUtils.forceGetFieldValue(b, sortname);
String str1 = value1.toString();
String str2 = value2.toString();
if (value1 instanceof Number && value2 instanceof Number) {
int maxlen = Math.max(str1.length(), str2.length());
str1 = ListUtils.addZero2Str((Number) value1, maxlen);
str2 = ListUtils.addZero2Str((Number) value2, maxlen);
} else if (value1 instanceof Date && value2 instanceof Date) {
long time1 = ((Date) value1).getTime();
long time2 = ((Date) value2).getTime();
int maxlen = Long.toString(Math.max(time1, time2)).length();
str1 = ListUtils.addZero2Str(time1, maxlen);
str2 = ListUtils.addZero2Str(time2, maxlen);
}
if (isAsc) {
ret = str1.compareTo(str2);
} else {
ret = str2.compareTo(str1);
}
return ret;
}
/**
* 给数字对象按照指定长度在左侧补0.
*
* 使用案例: addZero2Str(11,4) 返回 "0011", addZero2Str(-18,6)返回 "-000018"
*
* @param numObj
* 数字对象
* @param length
* 指定的长度
* @return
*/
public static String addZero2Str(Number numObj, int length) {
NumberFormat nf = NumberFormat.getInstance();
// 设置是否使用分组
nf.setGroupingUsed(false);
// 设置最大整数位数
nf.setMaximumIntegerDigits(length);
// 设置最小整数位数
nf.setMinimumIntegerDigits(length);
return nf.format(numObj);
}
/**
* 获取指定对象的指定属性值(去除private,protected的限制)
*
* @param obj
* 属性名称所在的对象
* @param fieldName
* 属性名称
* @return
* @throws Exception
*/
public static Object forceGetFieldValue(Object obj, String fieldName) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
Object object = null;
boolean accessible = field.isAccessible();
if (!accessible) {
// 如果是private,protected修饰的属性,需要修改为可以访问的
field.setAccessible(true);
object = field.get(obj);
// 还原private,protected属性的访问性质
field.setAccessible(accessible);
return object;
}
object = field.get(obj);
return object;
}
}
2.3Mapper
@Select("<script> SELECT * from " + ALARM_TABLE_NAME +
"<where>" +
"<if test='item.name != null'> name like '%" + "${item.name}" + "%'</if>" +
"<if test='item.componentId != null'> AND componentId = #{item.componentId} </if>" +
"<if test='item.componentInstanceId != null'> AND componentInstanceId = #{item.componentInstanceId} </if>" +
"<if test='item.levelListStr != null'> AND level in ${item.levelListStr} </if>" +
"<if test='item.alarmStateList != null'> AND CONCAT(confirmState,handState) in ${item.alarmStateListStr} </if>" +
"<if test='item.latestHappenStartTime != null' > AND latestHappenTime <![CDATA[>=]]> #{item.latestHappenStartTime}</if>" +
"<if test='item.latestHappenEndTime != null' > AND latestHappenTime <![CDATA[<=]]> #{item.latestHappenEndTime}</if>" +
"<if test='item.handStartTime != null' > AND handTime <![CDATA[>=]]> #{item.handStartTime}</if>" +
"<if test='item.handEndTime != null' > AND handTime <![CDATA[<=]]> #{item.handEndTime}</if>" +
"<if test='item.shockMark != null'> AND shockMark = #{item.shockMark} </if>" +
"</where> ORDER BY id DESC </script>")
List<Alarm> searchListByName(@Param("item") SearchCurrentAlarmQuery searchQuery);
3.告警排序字段(枚举类)
public enum AlarmSortEnum {
/**
* 首次发生时间
**/
FIRST_HAPPEN_TIME(0, "firstHappenTime"),
/**
* 级别
**/
LEVEL(1, "level"),
/**
* 名称
**/
NAME(2, "name"),
/**
* 组件实例名称
**/
COMPONENT_INSTANCE_NAME(3, "componentInstanceName"),
/**
* 确认状态
**/
CONFIRM_STATE(4, "confirmState"),
/**
* 确认时间
**/
CONFIRM_TIME(5, "confirmTime"),
/**
* 确认人
**/
HANDLER(6, "handler"),
/**
* 清除状态
**/
HAND_STATE(7, "handState"),
/**
* 清除时间
**/
HAND_TIME(8, "handTime"),
/**
* 清除时间
**/
INSTANCE(9, "instance");
private final int key;
private final String value;
public int getKey() {
return key;
}
public String getValue() {
return value;
}
AlarmSortEnum(int key, String value) {
this.key = key;
this.value = value;
}
/**
* 判断数值是否属于枚举类的值
*
* @param key
* @return
*/
public static boolean isInclude(int key) {
boolean include = false;
for (AlarmSortEnum e : AlarmSortEnum.values()) {
if (e.key == key) {
include = true;
break;
}
}
return include;
}
public static String getName(int key) {
String value = "";
for (AlarmSortEnum e : AlarmSortEnum.values()) {
if (e.key == key) {
value = e.getValue();
break;
}
}
return value;
}
}
推荐阅读
-
多条件的分页查询
-
解决mybatis一对多查询问题时的只显示一条数据的问题(查询部门的同时把所属部门的员工信息查出来)关联查询
-
oracle:查询各组最新的一条数据(按照某个条件)
-
Mybatis06----查询多对一,一对多的处理
-
Spring Data JPA整合REST客户端Feign时: 分页查询的反序列化问题 博客分类: spring Spring Data 序列化 分页 Feign
-
ssm+vue+ElementUI实现增删改查及带条件分页查询demo
-
Elasticsearch 全文搜索 (二) - 多词查询及查询的合并 博客分类: Elasticsearch elasticsearch全文搜索多词合并
-
Yii2中hasOne、hasMany及多对多关联查询的用法详解
-
JDBC使用游标实现分页查询的方法
-
如何快速开发树形列表和分页查询整合的Winform程序界面? DevExpress.NETwinform