diff --git a/src/main/java/cn/lihongjie/coal/base/dto/CommonQuery.java b/src/main/java/cn/lihongjie/coal/base/dto/CommonQuery.java index f0784030..12dd5616 100644 --- a/src/main/java/cn/lihongjie/coal/base/dto/CommonQuery.java +++ b/src/main/java/cn/lihongjie/coal/base/dto/CommonQuery.java @@ -3,12 +3,16 @@ package cn.lihongjie.coal.base.dto; import cn.lihongjie.coal.exception.BizException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.CaseFormat; import com.google.common.base.Splitter; +import io.hypersistence.utils.hibernate.query.ListResultTransformer; import io.vavr.Function4; import io.vavr.Tuple; import io.vavr.Tuple2; +import jakarta.persistence.EntityManager; +import jakarta.persistence.Query; import jakarta.persistence.criteria.*; import jakarta.persistence.metamodel.Attribute; import jakarta.persistence.metamodel.EntityType; @@ -17,16 +21,20 @@ import lombok.*; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.formula.functions.T; import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; +import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @Data @@ -37,6 +45,8 @@ public class CommonQuery { Function4> map = new HashMap<>(); + public static Map classMap = new HashMap<>(); + static { map.put( Tuple.of("like", String.class), @@ -502,16 +512,20 @@ public class CommonQuery { map.put( Tuple.of("in", String.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), - Arrays.stream(getArray(x)).map(i -> c.convert(i, String.class)).toList()); + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), + Arrays.stream(getArray(x)) + .map(i -> c.convert(i, String.class)) + .toList()); }); map.put( Tuple.of("in", Integer.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Integer.class)) .toList()); @@ -520,8 +534,9 @@ public class CommonQuery { map.put( Tuple.of("in", Long.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Long.class)) .toList()); @@ -530,8 +545,9 @@ public class CommonQuery { map.put( Tuple.of("in", Double.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Double.class)) .toList()); @@ -539,8 +555,9 @@ public class CommonQuery { map.put( Tuple.of("in", BigDecimal.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, BigDecimal.class)) .toList()); @@ -549,8 +566,9 @@ public class CommonQuery { map.put( Tuple.of("in", LocalDate.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, LocalDate.class)) .toList()); @@ -558,8 +576,9 @@ public class CommonQuery { map.put( Tuple.of("in", LocalDateTime.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, LocalDateTime.class)) .toList()); @@ -568,8 +587,9 @@ public class CommonQuery { map.put( Tuple.of("nin", String.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, String.class)) .toList()) @@ -579,8 +599,9 @@ public class CommonQuery { map.put( Tuple.of("nin", Integer.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Integer.class)) .toList()) @@ -590,8 +611,9 @@ public class CommonQuery { map.put( Tuple.of("nin", Long.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Long.class)) .toList()) @@ -601,8 +623,9 @@ public class CommonQuery { map.put( Tuple.of("nin", Double.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, Double.class)) .toList()) @@ -611,8 +634,9 @@ public class CommonQuery { map.put( Tuple.of("nin", BigDecimal.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, BigDecimal.class)) .toList()) @@ -622,8 +646,9 @@ public class CommonQuery { map.put( Tuple.of("nin", LocalDate.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, LocalDate.class)) .toList()) @@ -632,8 +657,9 @@ public class CommonQuery { map.put( Tuple.of("nin", LocalDateTime.class), (Root root, CriteriaBuilder criteriaBuilder, QueryItem x, ConversionService c) -> { - return ((SqmCriteriaNodeBuilder)criteriaBuilder) - .in(parseKey(root, x.key), + return ((SqmCriteriaNodeBuilder) criteriaBuilder) + .in( + parseKey(root, x.key), Arrays.stream(getArray(x)) .map(i -> c.convert(i, LocalDateTime.class)) .toList()) @@ -641,18 +667,6 @@ public class CommonQuery { }); } - @SneakyThrows - public static String[] getArray(QueryItem x) { - if (!StringUtils.isEmpty(x.value)) { - - if (x.value.startsWith("[")){ - return new ObjectMapper().readValue(x.value, String[].class); - } - return x.value.split(","); - } - return new String[0]; - } - private List items; private Integer pageNo = 0; private Integer pageSize = Integer.MAX_VALUE; @@ -792,6 +806,306 @@ public class CommonQuery { }; } + static { + classMap.put("string", String.class); + classMap.put("integer", Integer.class); + classMap.put("long", Long.class); + classMap.put("double", Double.class); + classMap.put("bigdecimal", BigDecimal.class); + classMap.put("localdate", LocalDate.class); + classMap.put("localdatetime", LocalDateTime.class); + } + + @SneakyThrows + public static String[] getArray(QueryItem x) { + if (!StringUtils.isEmpty(x.value)) { + + if (x.value.startsWith("[")) { + return new ObjectMapper().readValue(x.value, String[].class); + } + return x.value.split(","); + } + return new String[0]; + } + + public Query nativeQuery( + EntityManager em, + ConversionService conversionService, + String s, + Class resultClass, + Boolean count) { + + StringBuilder sb = new StringBuilder(); + + RandomNameGenerator randomNameGenerator = new RandomNameGenerator(); + + String tableName = randomNameGenerator.generate(); + + HashMap paramMap = new HashMap<>(); + + if (count) { + sb.append("select count(1) from (").append(s).append(") as ").append(tableName); + } else { + + sb.append("select * from (").append(s).append(") as ").append(tableName); + } + + if (CollectionUtils.isNotEmpty(items)) { + sb.append(" where 1=1 and ("); + + items.forEach(x -> x.setGroup(StringUtils.defaultIfBlank(x.getGroup(), "default"))); + + Map> group = + items.stream().collect(Collectors.groupingBy(i -> i.group)); + + List orPredicates = new ArrayList<>(); + int index = 0; + for (List queryItems : group.values()) { + + if (index++ != 0) { + sb.append(" or "); + } + + sb.append("("); + int qindex = 0; + for (QueryItem queryItem : queryItems) { + + String varName = randomNameGenerator.generate(); + if (qindex++ != 0) { + sb.append(" and "); + } + sb.append(" ("); + switch (queryItem.opt) { + case "like": + sb.append(queryItem.key) + .append(" like '%' || ") + .append(":") + .append(varName) + .append(" || '%'"); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "nlike": + sb.append(queryItem.key) + .append(" not like '%' || ") + .append(":") + .append(varName) + .append(" || '%'"); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + + case "null": + sb.append(queryItem.key).append(" is null"); + break; + case "nnull": + sb.append(queryItem.key).append(" is not null"); + break; + case "eq": + sb.append(queryItem.key).append(" = ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "neq": + sb.append(queryItem.key).append(" != ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "between": + sb.append(queryItem.key) + .append(" between ") + .append(":") + .append(varName) + .append(" and ") + .append(":") + .append(varName) + .append("_2"); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, true)); + paramMap.put( + varName + "_2", + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "lt": + sb.append(queryItem.key).append(" < ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "le": + sb.append(queryItem.key).append(" <= ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "gt": + sb.append(queryItem.key).append(" > ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "ge": + sb.append(queryItem.key).append(" >= ").append(":").append(varName); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "empty": + sb.append("cardinality(").append(queryItem.key).append(") = 0"); + break; + case "nempty": + sb.append("cardinality(").append(queryItem.key).append(") > 0"); + break; + case "in": + sb.append(queryItem.key) + .append(" = any(") + .append(":") + .append(varName) + .append(")"); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + case "nin": + sb.append(queryItem.key) + .append(" != all(") + .append(":") + .append(varName) + .append(")"); + paramMap.put( + varName, + toNativeQueryParam(queryItem, conversionService, false)); + break; + default: + throw new RuntimeException("无法识别的查询 " + queryItem); + } + + sb.append(")"); + } + + sb.append(")"); + } + sb.append(")"); + } + + sb.append(" "); + Query query; + + if (!count) { + + if (CollectionUtils.isNotEmpty(orders)) { + sb.append(" order by "); + int index = 0; + for (Order order : orders) { + if (index++ != 0) { + sb.append(","); + } + sb.append(order.property).append(" ").append(order.direction.name()); + } + } + + sb.append(" limit ").append(pageSize).append(" offset ").append(pageNo * pageSize); + + query = em.createNativeQuery(sb.toString()); + + paramMap.forEach((k, v) -> query.setParameter(k, v)); + query.unwrap(org.hibernate.query.NativeQuery.class) + .setResultTransformer( + new ListResultTransformer() { + @SneakyThrows + @Override + public Object transformTuple(Object[] tuple, String[] aliases) { + + T object = resultClass.newInstance(); + + for (int i = 0; i < aliases.length; i++) { + String alias = aliases[i]; + Object value = tuple[i]; + + Field field = + ReflectionUtils.findField( + resultClass, + CaseFormat.LOWER_UNDERSCORE.to( + CaseFormat.LOWER_CAMEL, alias)); + + if (field != null) { + + ReflectionUtils.makeAccessible(field); + ReflectionUtils.setField( + field, + object, + conversionService.convert( + value, field.getType())); + } + } + + return object; + } + }); + } else { + + query = em.createNativeQuery(sb.toString()); + + paramMap.forEach((k, v) -> query.setParameter(k, v)); + } + + return query; + } + + private Object toNativeQueryParam( + QueryItem queryItem, ConversionService conversionService, boolean b) { + Class targetType = classMap.get(queryItem.type); + + switch (queryItem.opt) { + case "in": + case "nin": + return Arrays.stream(getArray(queryItem)) + .map( + i -> { + return conversionService.convert(i, targetType); + }) + .toList(); + case "between": + return b + ? conversionService.convert(queryItem.min, targetType) + : conversionService.convert(queryItem.max, targetType); + } + return conversionService.convert(queryItem.value, targetType); + } + + public static class RandomNameGenerator { + + private final Set names = new HashSet<>(); + + public String generate() { + + int count = 0; + + while (true) { + + count++; + + if (count > 100) { + throw new RuntimeException("无法生成随机名称"); + } + + String name = "t_" + ThreadLocalRandom.current().nextInt(1, 100000); + + if (names.contains(name)) { + continue; + } + + names.add(name); + return name; + } + } + } + @Data public static class Order { @@ -809,5 +1123,6 @@ public class CommonQuery { @Builder.Default private String group = "default"; private String min; private String max; + private String type; } } diff --git a/src/main/java/cn/lihongjie/coal/meterDayLog/entity/MeterDayLogEntity.java b/src/main/java/cn/lihongjie/coal/meterDayLog/entity/MeterDayLogEntity.java index 8583b296..0a5939f0 100644 --- a/src/main/java/cn/lihongjie/coal/meterDayLog/entity/MeterDayLogEntity.java +++ b/src/main/java/cn/lihongjie/coal/meterDayLog/entity/MeterDayLogEntity.java @@ -8,9 +8,34 @@ import jakarta.persistence.ManyToOne; import lombok.Data; import org.hibernate.annotations.Comment; +import org.hibernate.annotations.Formula; +import org.hibernate.annotations.Subselect; @Data @Entity +@Subselect(""" + + +select distinct on (DATE_TRUNC('day', time), meter_id, organization_id) id, + create_time, + create_user_id, + file_ids, + update_time, + update_user_id, + code, + name, + remarks, + sort_key, + status, + organization_id, + DATE_TRUNC('day', time) as time, + value, + meter_id +from t_meter_log + +order by DATE_TRUNC('day', time), meter_id, organization_id, t_meter_log.time desc + +""") public class MeterDayLogEntity extends OrgCommonEntity { @ManyToOne @@ -22,9 +47,8 @@ public class MeterDayLogEntity extends OrgCommonEntity { @Comment("抄表值") private java.lang.Double value; - @Comment("上次抄表值") + @Formula("( lag(value, 1, (select tm.init_value from t_meter tm where tm.id = meter_id)) over (partition by meter_id order by time asc ) )") private java.lang.Double previousValue; - - @Comment("使用量") + @Formula(" ( value - ( lag(value, 1, (select tm.init_value from t_meter tm where tm.id = meter_id)) over (partition by meter_id order by time asc ) ) )") private java.lang.Double usage; } diff --git a/src/main/java/cn/lihongjie/coal/meterDayLog/service/MeterDayLogService.java b/src/main/java/cn/lihongjie/coal/meterDayLog/service/MeterDayLogService.java index 1b8a7c0c..f0cadea9 100644 --- a/src/main/java/cn/lihongjie/coal/meterDayLog/service/MeterDayLogService.java +++ b/src/main/java/cn/lihongjie/coal/meterDayLog/service/MeterDayLogService.java @@ -3,7 +3,6 @@ package cn.lihongjie.coal.meterDayLog.service; import cn.lihongjie.coal.base.dto.CommonQuery; import cn.lihongjie.coal.base.dto.IdRequest; import cn.lihongjie.coal.base.service.BaseService; -import cn.lihongjie.coal.meter.entity.MeterEntity; import cn.lihongjie.coal.meterDayLog.dto.CreateMeterDayLogDto; import cn.lihongjie.coal.meterDayLog.dto.MeterDayLogDto; import cn.lihongjie.coal.meterDayLog.dto.UpdateMeterDayLogDto; @@ -14,7 +13,6 @@ import cn.lihongjie.coal.meterMonthLog.service.MeterMonthLogService; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.persistence.Query; import lombok.extern.slf4j.Slf4j; @@ -26,9 +24,6 @@ import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDate; -import java.time.LocalDateTime; - @Service @Slf4j @Transactional @@ -84,64 +79,4 @@ class MeterDayLogService extends BaseService { - Object[] result = (Object[]) o; - MeterDayLogEntity entity = new MeterDayLogEntity(); - entity.setMeter(meter); - entity.setTime(conversionService.convert(result[0], LocalDate.class)); - entity.setValue((Double) result[2]); - repository.save(entity); - }); - - Query nativeQuery2 = - entityManager.createNativeQuery( - """ - - - update t_meter_day_log ta - - - set previous_value = tb.previous_value, - usage = ta.value - tb.previous_value - - from ( - - select id, time, value, COALESCE(lag(value) over (order by time), value ) as previous_value from t_meter_day_log where meter_id = :meterId - ) tb - - where tb.id = ta.id - - - """); - - nativeQuery2.setParameter("meterId", meterId); - - nativeQuery2.executeUpdate(); - - - meterMonthLogService.syncMeter(meterId, time); - - } } diff --git a/src/main/java/cn/lihongjie/coal/meterLog/controller/MeterLogController.java b/src/main/java/cn/lihongjie/coal/meterLog/controller/MeterLogController.java index 1899cf1f..4c02adc3 100644 --- a/src/main/java/cn/lihongjie/coal/meterLog/controller/MeterLogController.java +++ b/src/main/java/cn/lihongjie/coal/meterLog/controller/MeterLogController.java @@ -51,4 +51,5 @@ public class MeterLogController { public Page list(@RequestBody CommonQuery request) { return this.service.list(request); } + } diff --git a/src/main/java/cn/lihongjie/coal/meterLog/dto/MeterLogDto.java b/src/main/java/cn/lihongjie/coal/meterLog/dto/MeterLogDto.java index 0fcecb4f..954f2148 100644 --- a/src/main/java/cn/lihongjie/coal/meterLog/dto/MeterLogDto.java +++ b/src/main/java/cn/lihongjie/coal/meterLog/dto/MeterLogDto.java @@ -11,6 +11,8 @@ import org.hibernate.annotations.Comment; public class MeterLogDto extends OrgCommonDto { private MeterDto meter; + private String meterId; + @Comment("抄表时间") private java.time.LocalDateTime time; diff --git a/src/main/java/cn/lihongjie/coal/meterLog/entity/MeterLogEntity.java b/src/main/java/cn/lihongjie/coal/meterLog/entity/MeterLogEntity.java index 114dccf9..f79be506 100644 --- a/src/main/java/cn/lihongjie/coal/meterLog/entity/MeterLogEntity.java +++ b/src/main/java/cn/lihongjie/coal/meterLog/entity/MeterLogEntity.java @@ -1,12 +1,9 @@ package cn.lihongjie.coal.meterLog.entity; -import cn.lihongjie.coal.annotation.HyperTable; import cn.lihongjie.coal.base.entity.OrgCommonEntity; import jakarta.persistence.Entity; -import jakarta.persistence.Index; import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; import lombok.Data; @@ -15,9 +12,6 @@ import org.hibernate.annotations.Formula; @Data @Entity -@HyperTable -@Table(indexes = {@Index(columnList = "id")}) - public class MeterLogEntity extends OrgCommonEntity { @ManyToOne private cn.lihongjie.coal.meter.entity.MeterEntity meter; diff --git a/src/main/java/cn/lihongjie/coal/meterLog/service/MeterLogService.java b/src/main/java/cn/lihongjie/coal/meterLog/service/MeterLogService.java index 8b13caaf..1b0305fd 100644 --- a/src/main/java/cn/lihongjie/coal/meterLog/service/MeterLogService.java +++ b/src/main/java/cn/lihongjie/coal/meterLog/service/MeterLogService.java @@ -14,7 +14,6 @@ import cn.lihongjie.coal.meterMonthLog.service.MeterMonthLogService; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.persistence.Query; import lombok.extern.slf4j.Slf4j; @@ -25,19 +24,11 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StopWatch; - -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; @Service @Slf4j @Transactional -public -class MeterLogService extends BaseService { +public class MeterLogService extends BaseService { @Autowired private MeterLogRepository repository; @Autowired private MeterLogMapper mapper; @@ -49,7 +40,7 @@ class MeterLogService extends BaseService { MeterLogEntity entity = mapper.toEntity(request); this.repository.save(entity); - syncMeterLog(entity.getMeter().getId(), request.getTime()); + return getById(entity.getId()); } @@ -58,22 +49,15 @@ class MeterLogService extends BaseService { this.mapper.updateEntity(entity, request); this.repository.save(entity); - syncMeterLog(entity.getMeter().getId(), request.getTime()); + return getById(entity.getId()); } public void delete(IdRequest request) { - List all = this.repository.findAllById(request.getIds()); - Map> groupByMeterId = all.stream().collect(Collectors.groupingBy(l -> l.getMeter().getId())); + this.repository.deleteAllById(request.getIds()); - - groupByMeterId.forEach((meterId, meterLogs) -> { - syncMeterLog(meterId, meterLogs.stream().sorted(Comparator.comparing(MeterLogEntity::getTime)).findFirst().map(MeterLogEntity::getTime).orElse(LocalDateTime.now())); - }); - - } public MeterLogDto getById(String id) { @@ -94,48 +78,10 @@ class MeterLogService extends BaseService { return page.map(this.mapper::toDto); } + + @Autowired MeterMonthLogService meterMonthLogService; @Autowired MeterDayLogService meterDayLogService; - public void syncMeterLog(String meterId, LocalDateTime time) { - log.info("syncMeterLog {} {} 开始同步", meterId, time); - - Query nativeQuery = - entityManager.createNativeQuery( - """ - - - update t_meter_log ta - - - set previous_value = tb.previous_value, - usage = ta.value - tb.previous_value - - from ( - - select id, time, value, COALESCE(lag(value) over (order by time), value ) as previous_value from t_meter_log where meter_id = :meterId - ) tb - - where tb.id = ta.id - - - """); - - nativeQuery.setParameter("meterId", meterId); -// nativeQuery.setParameter("time", time); - - StopWatch stopWatch = new StopWatch(); - stopWatch.start("syncMeterLog"); - int count = nativeQuery.executeUpdate(); - - stopWatch.stop(); - - stopWatch.start("syncMeterDayLog"); - - meterDayLogService.syncMeter(meterId, time); - stopWatch.stop(); - - log.info("syncMeterLog {} 更新了 {} 条数据\n {}", meterId, count, stopWatch.prettyPrint()); - } } diff --git a/src/main/java/cn/lihongjie/coal/meterMonthLog/entity/MeterMonthLogEntity.java b/src/main/java/cn/lihongjie/coal/meterMonthLog/entity/MeterMonthLogEntity.java index 63afab69..18ef73c2 100644 --- a/src/main/java/cn/lihongjie/coal/meterMonthLog/entity/MeterMonthLogEntity.java +++ b/src/main/java/cn/lihongjie/coal/meterMonthLog/entity/MeterMonthLogEntity.java @@ -8,9 +8,34 @@ import jakarta.persistence.ManyToOne; import lombok.Data; import org.hibernate.annotations.Comment; +import org.hibernate.annotations.Formula; +import org.hibernate.annotations.Subselect; @Data @Entity +@Subselect(""" + + +select distinct on (DATE_TRUNC('month', time), meter_id, organization_id) id, + create_time, + create_user_id, + file_ids, + update_time, + update_user_id, + code, + name, + remarks, + sort_key, + status, + organization_id, + DATE_TRUNC('month', time) as time, + value, + meter_id +from t_meter_log + +order by DATE_TRUNC('month', time), meter_id, organization_id, t_meter_log.time desc + +""") public class MeterMonthLogEntity extends OrgCommonEntity { @ManyToOne private cn.lihongjie.coal.meter.entity.MeterEntity meter; @@ -21,9 +46,9 @@ public class MeterMonthLogEntity extends OrgCommonEntity { @Comment("抄表值") private java.lang.Double value; - @Comment("上次抄表值") - private java.lang.Double previousValue; - @Comment("使用量") + @Formula("( lag(value, 1, (select tm.init_value from t_meter tm where tm.id = meter_id)) over (partition by meter_id order by time asc ) )") + private java.lang.Double previousValue; + @Formula(" ( value - ( lag(value, 1, (select tm.init_value from t_meter tm where tm.id = meter_id)) over (partition by meter_id order by time asc ) ) )") private java.lang.Double usage; } diff --git a/src/main/java/cn/lihongjie/coal/meterMonthLog/service/MeterMonthLogService.java b/src/main/java/cn/lihongjie/coal/meterMonthLog/service/MeterMonthLogService.java index b759a6cc..5e1e4645 100644 --- a/src/main/java/cn/lihongjie/coal/meterMonthLog/service/MeterMonthLogService.java +++ b/src/main/java/cn/lihongjie/coal/meterMonthLog/service/MeterMonthLogService.java @@ -3,7 +3,6 @@ package cn.lihongjie.coal.meterMonthLog.service; import cn.lihongjie.coal.base.dto.CommonQuery; import cn.lihongjie.coal.base.dto.IdRequest; import cn.lihongjie.coal.base.service.BaseService; -import cn.lihongjie.coal.meter.entity.MeterEntity; import cn.lihongjie.coal.meterMonthLog.dto.CreateMeterMonthLogDto; import cn.lihongjie.coal.meterMonthLog.dto.MeterMonthLogDto; import cn.lihongjie.coal.meterMonthLog.dto.UpdateMeterMonthLogDto; @@ -13,7 +12,6 @@ import cn.lihongjie.coal.meterMonthLog.repository.MeterMonthLogRepository; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.persistence.Query; import lombok.extern.slf4j.Slf4j; @@ -25,9 +23,6 @@ import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDate; -import java.time.LocalDateTime; - @Service @Slf4j @Transactional @@ -79,60 +74,4 @@ class MeterMonthLogService extends BaseService { - Object[] result = (Object[]) o; - MeterMonthLogEntity entity = new MeterMonthLogEntity(); - entity.setMeter(meter); - entity.setTime(conversionService.convert(result[0], LocalDate.class)); - entity.setValue((Double) result[2]); - repository.save(entity); - }); - - Query nativeQuery2 = - entityManager.createNativeQuery( - """ - - - update t_meter_month_log ta - - - set previous_value = tb.previous_value, - usage = ta.value - tb.previous_value - - from ( - - select id, time, value, COALESCE(lag(value) over (order by time), value ) as previous_value from t_meter_month_log where meter_id = :meterId - ) tb - - where tb.id = ta.id - - - """); - - nativeQuery2.setParameter("meterId", meterId); - - nativeQuery2.executeUpdate(); - } }