标准规范 - 如何编写通用 class 以通过实体的任何枚举字段过滤实体

Criteria Specification - How to write generic class to filter a entity by any enum field of the entity

我有一个实体 class,它有 3 个枚举字段。现在,我想编写一个规范 class 来根据这些枚举字段过滤记录。我知道我可以为每个枚举写一个谓词 class。但是,我想知道我是否可以编写任何通用 class 来过滤任何枚举。这将节省代码和维护工作。

下面是我的实体class。

@Entity
@Table(name = "customer_lead")
@Where(clause = ReusableFields.SOFT_DELETED_CLAUSE)
@Audited(withModifiedFlag = true)
@Data
public class Lead extends ReusableFields implements Serializable
{
    public Lead() {
        // TODO Auto-generated constructor stub
    }

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "lead_id", updatable = false, nullable = false)
    Long leadId;
    
    @Column(name="name")
    String customerName;
    
    @Column(name="primary_mobile")
    String primaryMobile;
    
    @Column(name="secondary_mobile")
    String secondaryMobile;
    
    @Column(name="email_id")
    String emailId;
    
    @Column(name="purpose")
    String purpose;
    
    @Column(nullable=true)
    @Enumerated(EnumType.STRING)
    PropertyTypeEnum propertyType;
    
    @Column
    @Enumerated(EnumType.STRING)
    SentimentEnum sentiment;

    
    @NonNull
    @Column(name="status",nullable=false)
    @Enumerated(EnumType.STRING)
    LeadStatusEnum status; 
}

是的。这是可以做到的。步骤

  1. 使用两种方法创建规范生成器class。一种是根据枚举 class 获取枚举值。第二个根据前一种方法返回的枚举值过滤枚举。
@Component
public class SpecificationsBuilder<T>
{
public Specification<T> whereEnumFieldEquals(String key, List<String> names, Class claz)
    {
        Specification<T> finalSpec = null;
        for (String name : names)
        {
            @SuppressWarnings("unchecked")
            Specification<T> internalSpec = (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> cb
                    .equal(root.get(key), getEnum(name, claz));
            finalSpec = specOrCondition(finalSpec, internalSpec);
        }
        return finalSpec;
    }

public static <E extends Enum<E>> E getEnum(String text, Class<E> klass)
    {
        return Enum.valueOf(klass, text);
    }
}
  1. 在你的主要 class。创建类型为 lead 的规范生成器实例,并通过传递 enum.class 作为参数来调用方法。下面的示例代码。 (注意这只是一个示例)
static SpecificationsBuilder<Lead> specbldr = new SpecificationsBuilder<Lead>();

specbldr.whereEnumFieldEquals(Lead_.SENTIMENT, sentiment, SentimentEnum.class));