如何对多个实体使用单个 JPA 规范类和方法

Sri*_*aik 2 java spring criteria-api spring-data-jpa spring-boot

我正在创建一个 Spring Boot 应用程序,其中包含产品、类别、机械、使用位置等实体。所有这些实体的共同点是它们都有一个名为 name 的 String 属性,并且可以使用 name 从 UI 中过滤。我已经编写了一个使用名称进行过滤的产品规范,并且它正在工作。下面是代码

public final class ProductSpecifications 
{

    public static Specification<Product> whereNameContains(String name)
    {
        Specification<Product> finalSpec = (Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb)
            -> cb.like(root.get(Product_.PRODUCT_NAME), "%"+name+"%");
        return finalSpec;
    }

    public static Specification<Product> whereNameEqauls(String name)
    {
        Specification<Product> finalSpec = (Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb)
            -> cb.equal(root.get(Product_.PRODUCT_NAME), name);
        return finalSpec;
    }
}

Run Code Online (Sandbox Code Playgroud)

现在的问题是我必须再次编写相同的代码来过滤其他实体,唯一的区别是类名(Product)、字段名称(Product_NAME)和方法的返回类型。我可以创建一个通用类和方法吗?我可以将类名和字段名作为参数传递给它,并返回相应返回类型的规范。

Ekl*_*vya 5

首先让你的SpecificationsBuilder通用

@Service
public final class SpecificationsBuilder<T>
{

    public static Specification<T> whereNameContains(String key,String name)
    {
        Specification<T> finalSpec = (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb)
            -> cb.like(root.get(key), "%"+name+"%");
        return finalSpec;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在控制器@Autowire中SpecificationsBuilder

@Autowire
private final SpecificationBuilder<Product> specificationBuilder;

public List<Product> getAll(String name) {
    Specification<Product> specification =
        specificationBuilder.whereNameContains(Product_.PRODUCT_NAME, name);
    List<Product> products = productRepo.findAll(specification);// pass the specifications
    return products;
  }
Run Code Online (Sandbox Code Playgroud)

您可以为SpecificationsBuilder 创建您自己的通用库,我有一个。您可以在这里找到详细信息