【问题标题】:Percentage calculation based on entity fields data in Spring data JPASpring data JPA中基于实体字段数据的百分比计算
【发布时间】:2022-10-18 02:00:10
【问题描述】:

如果实体有10个字段,5个字段有数据,5个字段在数据库记录中没有数据,那么该实体记录的百分比为50%。

我们如何使用 Spring data jpa 或 Java 中的任何现有库进行计算

【问题讨论】:

    标签: java sql spring-boot spring-data-jpa


    【解决方案1】:

    您可以尝试在实体类的瞬态字段中使用反射。

    @Transient
    public float getPercentDone() {
      var propDesc = BeanUtilsBean2.getInstance().getPropertyUtils().getPropertyDescriptors(this);
      var allProps = Arrays.stream(propDesc).filter(prop -> !"percentDone".equals(prop.getName()))
            .collect(Collectors.toList());
      var countNotNull = allProps.stream().filter(prop -> {
        try {
          return BeanUtilsBean2.getInstance().getProperty(this, prop.getName()) != null;
        } catch (Exception e) {
          return false;
        }
      }).count();
    
      return (countNotNull * 100.0f) / allProps.size();
    }
    

    我为此使用了来自 Apache Commons 的 BeanUtils,但如果你不能使用它,你可以使用开箱即用的反射来做同样的事情(它只是更长)。

    跳过字段

    要跳过 ids 和 join 字段等字段,您可以创建一个列表。并将过滤器替换为检查跳过属性列表的过滤器。如果你把它放在@MappedSuperclass 中,实体子项只需要覆盖列表。

    笔记percentDoneskippedProperties 本身都必须是跳过的字段。

    List<String> skippedProperties = List.of("percentDone", "skippedProperties", "id", "user");
    ...
    @Transient
    public float getPercentDone() {
      var propDesc = BeanUtilsBean2.getInstance().getPropertyUtils().getPropertyDescriptors(this);
      var allProps = Arrays.stream(propDesc)
            .filter (prop -> !skippedProperties.contains(prop.getName())
            .collect(Collectors.toList());
      var countNotNull = allProps.stream().filter(prop -> {
        try {
          return BeanUtilsBean2.getInstance().getProperty(this, prop.getName()) != null;
        } catch (Exception e) {
          return false;
        }
      }).count();
    
      return (countNotNull * 100.0f) / (allProps.size() - skippedProperties.size());
    }
    

    【讨论】:

    • 谢谢您的答复。在我的问题中,错过了一个场景。场景:我总共有 6 个字段,我只需要检查 3 个字段进行百分比计算,剩下 3 个字段需要跳过(字段类型是主键字段和关系键字段) public class Employee { private Long id; // 跳过私有字符串 firstName;私人字符串姓氏;私人 MailingAddressD 到地址; // 跳过私有 UploadFileD 到 profileImage; // 跳过私有字符串 websiteUrl; }。
    • 要跳过一个字段,您需要向流处理器添加一个额外的过滤子句。 allProps.stream().filter(p -&gt; !p.getName().equals("id").prop(prop -&gt; ...
    • 感谢您的答复。要跳过 id 字段,我将向流中传递额外的过滤器子句,对于地址和 profileImage 等其他字段,是否有任何其他方法可以检查而不是在过滤器子句中静态传递。我在剩余实体中有不同的数据类型(用户、公司等),我想编写一个逻辑来重用所有实体。如果您有其他想法,请给我建议。
    猜你喜欢
    • 1970-01-01
    • 2016-05-30
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多