如果您不想使用 QueryDSL,则必须编写自己的规范。首先,您需要JpaSpecificationExecutor
像以前一样扩展您的存储库。确保添加泛型虽然 ( JpaSpecificationExecutor<Some>
)。
之后,您必须创建三个规范(每列一个),在Spring 文档中,他们将这些规范定义为类中的静态方法。基本上,创建规范意味着您必须对Specification<Some>
只有一种方法要实现的toPredicate(Root<Some>, CriteriaQuery<?>, CriteriaBuilder)
.
如果您使用的是 Java 8,则可以使用 lambdas 创建匿名内部类,例如:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> {
// ...
};
}
}
对于实际实现,您可以使用它Root
来获取特定节点,例如。root.get("address")
. CriteriaBuilder
另一方面是定义where子句,例如。builder.equal(..., ...)
.
在你的情况下,你想要这样的东西:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.equal(root.get("address"), address);
}
}
或者,如果您想使用LIKE
查询,您可以使用:
public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.like(root.get("address"), "%" + address + "%");
}
}
现在您必须对要过滤的其他字段重复此操作。之后,您必须一起使用所有规范(使用and()
, or()
, ...)。然后您可以使用该repository.findAll(Specification)
方法根据该规范进行查询,例如:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(withAddress(address))
.and(withName(name))
.and(withDate(date));
}
您可以使用静态导入来导入withAddress()
,withName()
并withDate()
使其更易于阅读。该where()
方法也可以静态导入(来自Specification.where()
)。
请注意,上述方法可能必须进行调整,因为您不想过滤地址字段(如果它是null
. 你可以通过返回来做到这一点null
,例如:
public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(address == null ? null : withAddress(address))
.and(name == null ? null : withName(name))
.and(date == null ? null : withDate(date));
}