Spring Jpa 规范无法在子类中定位属性

问题描述

所以我有以下实体层次结构:

@MappedSuperClass
public abstract class BaseEntity {
    private Long id;
    private Date createAt;
    private Date updateAt;
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Post extends BaseEntity {
    private String creatorId;
    private String title;
    private String content;
}

@Entity
public class Article extends Post {
    private String category;  // article has category
}

@Entity
public class Journal extends Post {
    private Date expiration;  // journal has expiration
}

现在当我使用 Spring Jpa Specification 查询特定类别的文章时,它不起作用:

// define specification
public class ArticleSpecifications {
    public static Specification<Article> withCategory(String category) {
        (root,query,criteriaBuilder) ->
                criteriaBuilder.equal(root.get("category"),category)
    }
}

// repository
public interface PostRepository<T extends Post> extends JpaRepository<T,Long>,JpaSpecificationExecutor<T> { ... }


// usage: in some service class
@Autowired
private PostRepository<Article> articleRepository;
...

public void someMethod {
    ...
    // error here
    articleRepository.findAll(ArticleSpecifications.withCategory("news"),pageable);
    ...
}

错误信息:

java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [category] on this ManagedType [com.gladdev.galahad.base.BaseEntity]

只是想在这里了解为什么它会尝试在 BaseEntity 中查找“类别”。
Post 中定义的每个规范访问属性都可以正常工作。
是一些 spring jpa 规范错误还是我错过了什么?

解决方法

您可以使用 CriteriaBuilder.treat() 方法。

在 Criteria API 中,可以使用 CriteriaBuilder.treat() 方法之一将实体向下转换为子类实体:

https://docs.oracle.com/javaee/7/api/javax/persistence/criteria/CriteriaBuilder.html#treat-javax.persistence.criteria.Root-java.lang.Class-

public static Specification<Article> withCategory(String category) {
   return (root,query,criteriaBuilder) -> {
      Root<Article> article = criteriaBuilder.treat(root,Article.class);
      return criteriaBuilder.equal(article.get("category"),category);
   };
}