Java基于时间范围判断有效数据 如何获取指定日期的属性有效值
Java基于时间范围的属性有效值查询最优实现方案
以下方案同时覆盖数据库查询、Java内存查询两类使用场景,可根据实际业务选择。
场景1:仅含生效起始日(valid_from)的表结构
匹配规则
同属性名下,生效起始日小于等于查询日期的所有记录中,生效起始日最大的记录即为有效值。
以示例为例,2021-06-13查询时,符合条件的生效日为2020-01-01、2021-02-02,取最大的2021-02-02对应的值41,123。
SQL查询实现(数据存储在关系型数据库时优先用该方案)
假设表名为attribute_validity,字段为attr_name(属性名)、value(属性值)、valid_from(生效起始日,日期类型):
SELECT value FROM attribute_validity WHERE attr_name = 'attr1' AND valid_from <= '2021-06-13' ORDER BY valid_from DESC LIMIT 1;
Java内存查询实现(配置类数据已加载到内存时使用)
// 实体类定义 public class AttrValidity { private String attrName; private String value; private LocalDate validFrom; // 省略getter、setter、构造方法 } // 查询逻辑 public Optional<String> getValidValueOnlyFrom(String attrName, LocalDate queryDate, List<AttrValidity> allRecords) { return allRecords.stream() .filter(record -> attrName.equals(record.getAttrName())) // 过滤生效日晚于查询日期的记录 .filter(record -> !record.getValidFrom().isAfter(queryDate)) // 取生效日最大的记录 .max(Comparator.comparing(AttrValidity::getValidFrom)) .map(AttrValidity::getValue); }
场景2:同时含生效起始日(valid_from)、生效截止日(valid_to)的表结构
匹配规则
同属性名下,满足 valid_from <= 查询日期 < valid_to(左闭右开规则,避免时间段边界冲突)的记录即为有效值。
以示例为例,2021-06-13查询时,41,123的截止日为2021-04-02,早于查询日期不符合条件,最终取符合区间的41。
SQL查询实现
SELECT value FROM attribute_validity WHERE attr_name = 'attr1' AND valid_from <= '2021-06-13' AND valid_to > '2021-06-13' -- 若存在脏数据导致多条符合,加排序取最新生效的,避免返回异常 ORDER BY valid_from DESC LIMIT 1;
Java内存查询实现
// 扩展实体类 public class AttrValidityRange extends AttrValidity { private LocalDate validTo; // 省略getter、setter、构造方法 } // 查询逻辑 public Optional<String> getValidValueWithRange(String attrName, LocalDate queryDate, List<AttrValidityRange> allRecords) { return allRecords.stream() .filter(record -> attrName.equals(record.getAttrName())) .filter(record -> !record.getValidFrom().isAfter(queryDate)) .filter(record -> record.getValidTo().isAfter(queryDate)) // 兼容脏数据,多匹配结果时取最新生效的 .max(Comparator.comparing(AttrValidityRange::getValidFrom)) .map(AttrValidityRange::getValue); }
通用优化建议
- 时间字段统一用数据库原生日期类型、Java
LocalDate/LocalDateTime类型存储,不要用字符串,避免格式转换错误 - 永久生效的记录统一用
2100-01-01这类远日期作为valid_to值,不要用null,减少空判断逻辑,查询更统一 - 高频内存查询场景可提前将同属性的记录按
valid_from排序,用二分查找替代遍历,性能提升10倍以上 - 场景2的数据入库前要校验时间段不可重叠,避免查询出现多匹配结果的异常
内容的提问来源于stack exchange,提问作者foxbuur
相关产品推荐
相关产品推荐

