Java Spring数据JPA查询,过滤器?搜索引擎?JPQL?

Java Spring数据JPA查询,过滤器?搜索引擎?JPQL?,java,spring-boot,jpa,Java,Spring Boot,Jpa,我在JPA存储库中编写查询时遇到问题,因为我有一种基于父亲姓名等搜索父亲的方法 @Query("select * from father where # ???") List<Father> searchFather(@Param("fatherBirthDate") LocalDate fatherBirthDate, @Param("fatherFirstName") String fatherFirstName,

我在JPA存储库中编写查询时遇到问题,因为我有一种基于父亲姓名等搜索父亲的方法

@Query("select * from father where # ???")
List<Father> searchFather(@Param("fatherBirthDate") LocalDate fatherBirthDate,
                          @Param("fatherFirstName") String fatherFirstName,
                          @Param("fatherSurName") String fatherSurName)
  • 当我什么都不提供时,请返回所有父亲
  • 当我提供父亲的名字“乔恩”时,我期待着乔恩·斯诺和乔恩·阿尔比
  • 当我提供姓氏“COLBY”时,查询将返回HARRY COLBY

我尝试了一百万次,但我无法编写一个查询,当我不提供任何参数时,该查询将返回所有父亲,当我提供一些参数时,该查询将减少找到的父亲列表。

对于动态查询,您可以使用JPA的Criteria API

为了类型安全,您可以使用hibernate jpamodelgen Maven插件来生成元模型


Spring数据提供了规范API,它有更多的帮助类来使用Criteria API。

使用Spring Boot提供动态搜索的最简单方法是使用规范

在存储库类中启用按规范搜索:

public interface FatherRepository extends JpaRepository<Father, Long>, JpaSpecificationExecutor<Father> {}
公共接口父存储库扩展了JPA存储库,JPA指定执行器{}
创建规范类:

public class FatherSpecifications {
    public static Specification<Father> hasBirthdate(LocalDate birthdate) {
        return (father, cq, cb) -> Optional.ofNullable(birthdate).map(b -> cb.equal(father.get("birthdate"), b)).orElse(null);
    }

    public static Specification<Father> firstnameLike(String firstname) {
        return (father, cq, cb) -> Optional.ofNullable(firstname).map(f -> cb.like(father.get("firstname"), "%" + f + "%")).orElse(null);
    }

    public static Specification<Father> surnameLike(String surname) {
        return (father, cq, cb) -> Optional.ofNullable(surname).map(s -> cb.like(father.get("surname"), "%" + s + "%")).orElse(null);
    }
}
公共类父级规范{
公共静态规范hasBirthdate(LocalDate birthdate){
return(father,cq,cb)->可选的.ofNullable(birthdate).map(b->cb.equal(father.get(“birthdate”),b)).orElse(null);
}
公共静态规范firstnameLike(字符串firstname){
return(father,cq,cb)->Optional.ofNullable(firstname).map(f->cb.like(father.get(“firstname”),“%”+f+“%”)。orElse(null);
}
公共静态规范姓氏(字符串姓氏){
return(father,cq,cb)->可选的.of nullable(姓氏).map(s->cb.like(father.get(“姓氏”),“%”+s+“%”)。orElse(null);
}
}
然后,您可以在代码中的任何位置(父存储库自动连接的位置)搜索:

List fatherRepository=fatherRepository.findAll(Specification.where(FatherSpecifications.hasbirchdate(birthdate))和(FatherSpecifications.firstnameLike(firstname))和(FatherSpecifications.namelike(姓氏));
在我的示例中,我没有对列名使用“父”前缀,因为我认为这是多余的,因为它们已经是父实体的列。公共静态规范hasFirstName(String fatherName){return new Specification(){@Override public Predicate toPredicate(根根目录,CriteriaQuery查询,CriteriaBuilder CriteriaBuilder){Join JoinedDather=Root.Join(“父”);返回可选的.ofNullable(父名称).map(s->CriteriaBuilder.like(JoinedDather.get(“firstName”),“%”+s+“%”)。orElse(null);}; }}
public class FatherSpecifications {
    public static Specification<Father> hasBirthdate(LocalDate birthdate) {
        return (father, cq, cb) -> Optional.ofNullable(birthdate).map(b -> cb.equal(father.get("birthdate"), b)).orElse(null);
    }

    public static Specification<Father> firstnameLike(String firstname) {
        return (father, cq, cb) -> Optional.ofNullable(firstname).map(f -> cb.like(father.get("firstname"), "%" + f + "%")).orElse(null);
    }

    public static Specification<Father> surnameLike(String surname) {
        return (father, cq, cb) -> Optional.ofNullable(surname).map(s -> cb.like(father.get("surname"), "%" + s + "%")).orElse(null);
    }
}
List<Father> fathers = fatherRepository.findAll(Specification.where(FatherSpecifications.hasBirthdate(birthdate)).and(FatherSpecifications.firstnameLike(firstname)).and(FatherSpecifications.surnameLike(surname)));