问题描述
我有这个 JobPosting 类和这个实体的存储库接口。我希望能够搜索 JobPosting 类的公司、技能、职位和城市字段的所有组合。我知道的唯一方法是在存储库界面中创建不同的方法。例如,要按城市和标题搜索,我需要创建一个名为 findByCityIdAndTitleContaining(Long id,String title) 的方法。为了按技能和职称搜索,我需要创建一个名为 LfindBySkillsIdAndTitleContaining(Long id,String title) 的方法。问题是如果我为每种可能性创建不同的方法,就会有太多的方法。有没有更好的办法?
@Entity
public class JobPosting
{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Company company;
private Date publishedAt;
private String title,description;
private boolean isActive;
@ManyToOne
private City city;
@ManyToMany
@JoinTable(name="job_posting_skill",joinColumns=@JoinColumn(name="job_posting_id"),inverseJoinColumns=@JoinColumn(name="skill_id"))
private Set<Skill> skills;
}
存储库:
package app.repository;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import app.entity.JobPosting;
public interface JobPostingRepository extends JpaRepository<JobPosting,Long>
{
Page<JobPosting> findAll(Pageable pageable);
List<JobPosting> findByCompanyId(long companyId);
List<JobPosting> findByTitleContaining(String title);
List<JobPosting> findBySkillsId(Long id);
List<JobPosting> findByCityId(Long id);
}
解决方法
Spring Data 提供了可以满足您需求的 JpaSpecificationExecutor。
List<T> findAll(Specification<T> spec)
Returns all entities matching the given Specification.
规范有一个谓词方法:
interface Specification<T> {
Predicate toPredicate(Root<T> root,CriteriaQuery query,CriteriaBuilder cb);
}
它有一个 CriteriaBuilder,所以理论上你仍然需要定义你需要匹配的内容,但是你不必创建多个 findByXYZ。
为了能够使用 findAll(Specification),您的存储库需要扩展 org.springframework.data.jpa.repository.JpaSpecificationExecutor<T>:
用法示例: