Browse Source

告警记录分组统计数量

wangsufei 2 years ago
parent
commit
5859b5a86a

+ 3 - 1
readme.md

@@ -21,4 +21,6 @@
 - 支持设备维保服务
 # v3.0.0
 - 将报警中台dmp-alarm的代码合并到energy-alarm-service服务
-- 将energy-alarm-service服务spring服务名更改为dmp-alarm
+- 将energy-alarm-service服务spring服务名更改为dmp-alarm
+# custom_v3.0.0_zhaoshang
+- 告警记录AlarmRecord增加分组统计的方法

+ 7 - 0
src/main/java/com/persagy/apm/dmpalarm/controller/AlarmRecordController.java

@@ -16,6 +16,8 @@ import com.persagy.apm.dmpalarm.web.PagedResponse;
 
 import io.swagger.annotations.Api;
 
+import java.util.List;
+
 /**
  * 报警记录控制层
  * 
@@ -36,6 +38,11 @@ public class AlarmRecordController {
 		return alarmRecordService.query(criteria);
 	}
 
+	@PostMapping("/query-group-category")
+	public List<AlarmRecord> groupByQuery(@RequestBody JsonCriteria criteria) {
+		return alarmRecordService.queryGroupByCategory(criteria);
+	}
+
 	@PostMapping("/create")
 	public MapResponse create(@RequestBody AlarmRecord alarmRecord) {
 		return alarmRecordService.create(alarmRecord);

+ 7 - 0
src/main/java/com/persagy/apm/dmpalarm/criteria/JsonCriteria.java

@@ -40,6 +40,9 @@ import lombok.Setter;
  *     ],
  *     "withColumns": [
  *     		"name", "age"
+ *     ],
+ *     "groupByColumns": [
+ *     		"name", "age"
  *     ]
  * }
  *           </pre>
@@ -77,6 +80,10 @@ public class JsonCriteria {
 	@Setter
 	private Set<String> withColumns = new HashSet<>();
 
+	@Getter
+	@Setter
+	private Set<String> groupByColumns = new HashSet<>();
+
 	@Data
 	public static class Order {
 		private String column;

+ 15 - 0
src/main/java/com/persagy/apm/dmpalarm/model/DateTimeRange.java

@@ -0,0 +1,15 @@
+package com.persagy.apm.dmpalarm.model;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 时间范围
+ * @author wangsufei
+ */
+@Data
+public class DateTimeRange {
+	private Date startTime;
+	private Date endTime;
+}

+ 4 - 0
src/main/java/com/persagy/apm/dmpalarm/service/IAlarmRecordService.java

@@ -5,6 +5,8 @@ import com.persagy.apm.dmpalarm.model.AlarmRecord;
 import com.persagy.apm.dmpalarm.web.MapResponse;
 import com.persagy.apm.dmpalarm.web.PagedResponse;
 
+import java.util.List;
+
 /**
  * 报警记录(AlarmRecord) service接口
  *
@@ -15,6 +17,8 @@ public interface IAlarmRecordService {
 
 	public PagedResponse<AlarmRecord> query(JsonCriteria criteria);
 
+	public List<AlarmRecord> queryGroupByCategory(JsonCriteria criteria);
+
 	public MapResponse create(AlarmRecord alarmRecord);
 
 	public MapResponse update(AlarmRecord alarmRecord);

+ 17 - 0
src/main/java/com/persagy/apm/dmpalarm/service/IShardingService.java

@@ -3,6 +3,7 @@ package com.persagy.apm.dmpalarm.service;
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.persagy.apm.dmpalarm.model.ShardingEntity;
@@ -59,6 +60,22 @@ public interface IShardingService {
 			Integer pageSize,Date startTime,Date endTime);
 
 	/**
+	 * 自定义分组统计
+	 * @param cls 类名
+	 * @param columns 查询列名
+	 * @param groupByColumns 分组列名
+	 * @param queryWrapper 查询条件
+	 * @param pageNo 当前页码
+	 * @param pageSize 页大小
+	 * @param startTime 分表起始
+	 * @param endTime 分表结束
+	 * @param <T> 类
+	 * @return T
+	 */
+	<T> List<T> selectShardingCustomGroupByPageList(Class<T> cls, Set<String> columns, Set<String> groupByColumns, QueryWrapper<T> queryWrapper, Integer pageNo,
+															 Integer pageSize, Date startTime, Date endTime);
+
+	/**
 	 * 新增
 	 * 
 	 * @param obj

+ 63 - 0
src/main/java/com/persagy/apm/dmpalarm/service/impl/AlarmRecordServiceImpl.java

@@ -11,6 +11,7 @@ import java.util.UUID;
 
 import javax.annotation.Resource;
 
+import com.persagy.apm.dmpalarm.model.DateTimeRange;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -145,6 +146,68 @@ public class AlarmRecordServiceImpl extends BaseServiceImpl<BaseMapper<AlarmReco
         return new PagedResponse<>();
     }
 
+    @Override
+    public List<AlarmRecord> queryGroupByCategory(JsonCriteria jsonCriteria) {
+        try {
+            // 构建查询的时间
+            DateTimeRange triggerTimeRange = buildDateTimeRange(jsonCriteria.getCriteria().getJSONObject("triggerTime"));
+
+            // 自定义分组的统计
+            return shardingService.selectShardingCustomGroupByPageList(AlarmRecord.class,jsonCriteria.getWithColumns(),jsonCriteria.getGroupByColumns(), buildAlarmRecordQueryWrapper(jsonCriteria),
+                    jsonCriteria.getPage(), jsonCriteria.getSize(), triggerTimeRange.getStartTime(), triggerTimeRange.getEndTime());
+        } catch (Exception e) {
+            log.error("alarmRecord query page error JsonCriteria is {}", jsonCriteria.toString(), e);
+        }
+        return new ArrayList<>();
+    }
+
+    /**
+     * 构建查询的时间范围
+     * @param triggerTimeJson 查询时间相关的对象
+     * @return DateTimeRange
+     */
+    private DateTimeRange buildDateTimeRange(JSONObject triggerTimeJson){
+        DateTimeRange dateTimeRange=new DateTimeRange();
+        if (null != triggerTimeJson && !triggerTimeJson.isEmpty()) {
+            String gt = triggerTimeJson.getString("$gt");
+            gt = StringUtils.isNotBlank(gt) ? gt : triggerTimeJson.getString("$gte");
+            if (StringUtils.isNotBlank(gt)) {
+                dateTimeRange.setStartTime(DateUtil.parse(gt));
+            }
+            String lt = triggerTimeJson.getString("$lt");
+            lt = StringUtils.isNotBlank(lt) ? lt : triggerTimeJson.getString("$lte");
+            if (StringUtils.isNotBlank(lt)) {
+                dateTimeRange.setEndTime(DateUtil.parse(lt));
+            }
+        }
+        return dateTimeRange;
+    }
+
+    /**
+     * 构建查询条件
+     * @param jsonCriteria 查询条件
+     * @return QueryWrapper<AlarmRecord>
+     */
+    private QueryWrapper<AlarmRecord> buildAlarmRecordQueryWrapper(JsonCriteria jsonCriteria){
+        QueryWrapper<AlarmRecord> queryWrapper = criteriaUtils.handleAlarmConditions(jsonCriteria,
+                AlarmRecord.class);
+        this.addAlarmQueryCondition(jsonCriteria.getCriteria(), queryWrapper);
+        JSONObject supplementJsonObject = jsonCriteria.getCriteria().getJSONObject("supplement");
+        if (null != supplementJsonObject && !supplementJsonObject.isEmpty()) {
+            for (Entry<String, Object> entry : supplementJsonObject.entrySet()) {
+                List<Object> param=new ArrayList<>();
+                if (entry.getValue() instanceof List) {
+                    param = (List<Object>) entry.getValue() ;
+                }else {
+                    param.add(entry.getValue());
+                }
+                String strArray =CharSequenceUtil.join("\",\"", param);
+                queryWrapper.apply("JSON_CONTAINS( JSON_ARRAY(\""+strArray+"\"), JSON_ARRAY(supplement->'$."+entry.getKey()+"'))") ;
+            }
+        }
+        return queryWrapper;
+    }
+
     public Date getCreateTime(List<AlarmLog> alarmLogList, String type, int after) {
         Date createTime = null;
         if (!CollectionUtils.isEmpty(alarmLogList)) {

+ 108 - 11
src/main/java/com/persagy/apm/dmpalarm/service/impl/ShardingServiceImpl.java

@@ -1,15 +1,10 @@
 package com.persagy.apm.dmpalarm.service.impl;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Objects;
 
+import com.baomidou.mybatisplus.core.toolkit.*;
 import org.apache.ibatis.type.TypeHandler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -21,10 +16,6 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.baomidou.mybatisplus.core.toolkit.Assert;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.persagy.apm.dmpalarm.dao.ShardingMapper;
 import com.persagy.apm.dmpalarm.model.ShardingEntity;
 import com.persagy.apm.dmpalarm.service.IShardingService;
@@ -49,6 +40,9 @@ public class ShardingServiceImpl implements IShardingService {
 
 	private static final String ALL_FIELD_SQL = "SELECT * ";
 
+	// 自定义查询的列
+	private static final String CUSTOM_FIELD_SQL = "SELECT CUSTOM_FIELD ";
+
 	public static final String SHARDING_COLUMN = "trigger_time";
 
 	private static final String ASC = "asc";
@@ -140,6 +134,109 @@ public class ShardingServiceImpl implements IShardingService {
 	}
 
 	@Override
+	public <T> List<T> selectShardingCustomGroupByPageList(Class<T> cls, Set<String> columns, Set<String> groupByColumns, QueryWrapper<T> queryWrapper, Integer pageNo,
+														   Integer pageSize, Date startTime, Date endTime) {
+		List<T> resultList = new ArrayList<>();
+		List<ShardingEntity> tableList = this.selectShardingGroupTableCount(cls, queryWrapper, startTime, endTime);
+
+		for (int i = 0; i < tableList.size(); i++) {
+			resultList.addAll(queryCustomGroupBy(cls,columns,groupByColumns, queryWrapper,
+					this.getShardingEntityList(tableList.get(i))));
+		}
+		return resultList;
+	}
+
+	/**
+	 *
+	 * @param customGroupByColumns 自定义分组的列
+	 * @param queryWrapper 查询条件
+	 * @param newParamValueMap 参数
+	 * @param sqlPrefix SQL前缀
+	 * @param tableNameList 表名
+	 * @param <T> 对象
+	 * @return String
+	 */
+	private <T> String shardingSplicingGroupBySQL(String customGroupByColumns, QueryWrapper<?> queryWrapper,
+												  Map<String, Object> newParamValueMap, String sqlPrefix, List<ShardingEntity> tableNameList) {
+		List<String> tempQuerySqlList = new ArrayList<>();
+		String customSqlSegment = queryWrapper.getCustomSqlSegment();
+		String orderBySql = "";
+		if (customSqlSegment.contains(ORDER_BY)) {
+			orderBySql = customSqlSegment.substring(customSqlSegment.lastIndexOf(ORDER_BY));
+		}
+		if (orderBySql.contains(SHARDING_COLUMN)) {
+			String[] orderBys = orderBySql.split(",");
+			for (String string : orderBys) {
+				if(!string.contains(SHARDING_COLUMN)) {
+					continue;
+				}
+				int lastIndex = string.lastIndexOf(",");
+				lastIndex=lastIndex == -1?string.length():lastIndex;
+				int index = string.indexOf(SHARDING_COLUMN);
+				String orderByString = string.substring(index, lastIndex);
+				if (orderByString.toUpperCase().contains(ASC.toUpperCase()) || !orderByString.toUpperCase().contains(DESC.toUpperCase())) {
+					Collections.reverse(tableNameList);
+				}
+			}
+		}
+		Map<String, Object> oldParamValueMap = queryWrapper.getParamNameValuePairs();
+		for (int i = 0; i < tableNameList.size(); i++) {
+			ShardingEntity shardingEntity = tableNameList.get(i);
+			String sqlWhere = new String(customSqlSegment.getBytes()).replace(orderBySql, "");
+			for (Map.Entry<String, Object> entry : oldParamValueMap.entrySet()) {
+				String oldParamKey = Constants.WRAPPER + ".paramNameValuePairs." + entry.getKey();
+				String newParamKey = "table@" + shardingEntity.getTableName() + "@" + entry.getKey();
+				sqlWhere = sqlWhere.replace(oldParamKey, Constants.WRAPPER_DOT + newParamKey);
+				newParamValueMap.put(newParamKey, entry.getValue());
+			}
+			// 分组字段不为空,则组装分组SQL
+			if (StringUtils.isNotBlank(customGroupByColumns)) {
+				sqlWhere += " GROUP BY " + customGroupByColumns;
+			}
+			tempQuerySqlList.add(sqlPrefix + ",'" + shardingEntity.getTableName()
+					+ "' tableName,CONVERT(SUBSTRING_INDEX('" + shardingEntity.getTableName()
+					+ "','_',-1),SIGNED) suffix  FROM " + shardingEntity.getTableName() + " " + sqlWhere);
+		}
+		if (tempQuerySqlList.size() > 1) {
+			return CharSequenceUtil.join(" UNION ALL ", tempQuerySqlList);
+		} else {
+			return tempQuerySqlList.get(0);
+		}
+	}
+
+	/**
+	 * 自定义分组统计查询
+	 * @param cls 实体
+	 * @param columns 查询的列
+	 * @param groupByColumns 分组的列
+	 * @param queryWrapper 查询条件
+	 * @param tableList 表名集合
+	 * @param <T> 对象
+	 * @return List<T>
+	 */
+	private <T> List<T> queryCustomGroupBy(Class<T> cls, Set<String> columns, Set<String> groupByColumns, QueryWrapper<T> queryWrapper, List<ShardingEntity> tableList) {
+		if (CollectionUtils.isEmpty(columns)){
+			return new ArrayList<>();
+		}
+		Map<String, Object> newParamValueMap = new HashMap<>();
+
+		// 替换为传参的列
+		String selectFieldSql=CUSTOM_FIELD_SQL.replace("CUSTOM_FIELD",CharSequenceUtil.join(", ", columns));
+		// 拼接分组查询的SQL
+		String sql = this.shardingSplicingGroupBySQL(CharSequenceUtil.join(", ",groupByColumns), queryWrapper, newParamValueMap, selectFieldSql, tableList);
+		// 拼接为完成的查询SQL
+		sql = ALL_FIELD_SQL + " FROM (" + sql + ") ls";
+
+		List<Map<String, Object>> list = shardingMapper.selectShardingListMap(sql, newParamValueMap);
+		if (CollectionUtils.isEmpty(list)){
+			return new ArrayList<>();
+		}
+
+		// 组装查询结果
+		return handleResultList(cls, list);
+	}
+
+	@Override
 	public void save(Object obj, Date time) {
 		TableInfo tableInfo = TableInfoHelper.getTableInfo(obj.getClass());
 		String suffix = DateUtil.format(time, DatePatternStyle.PATTERN_YYYYMM);