问题描述
所以我有以下实体层次结构:
@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()
方法之一将实体向下转换为子类实体:
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);
};
}