这是一个 SSCCE ,显示研究,不是骗子而且是主题!!!
Spring Boot REST 服务和 MySQL 在这里。我有以下 Profile
实体:
@Entity
@Table(name = "profiles")
public class Profile extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "profile_given_name")
private String givenName;
@Column(name = "profile_surname")
private String surname;
@Column(name = "profile_is_male")
private Integer isMale;
@Column(name = "profile_height_meters", columnDefinition = "DOUBLE")
private BigDecimal heightMeters;
@Column(name = "profile_weight_kilos", columnDefinition = "DOUBLE")
private BigDecimal weightKilos;
@Column(name = "profile_dob")
private Date dob;
// Getters, setters & ctor down here
}
我还有一个 ProfileController
并且我想公开一个 GET 端点,它提供了一种非常灵活/稳健的方式来搜索 Profiles
基于大量标准:
# Search for women between 1.2 and 1.8 meters tall.
GET /v1/profiles?isMale=0&heightMeters={"gt": 1.2, "lt": 1.8}
# Search for men born after Jan 1, 1990 who weigh less than 100 kg.
GET /v1/profiles?isMale=1&dob={"gt" : "1990-01-01 00:00:00"}&weightKilos={"lt": 100.0}
等等
所以这是我的控制器:
@RestController
@RequestMapping("/v1/profiles")
public class ProfileResource {
@Autowired
ProfileRepository profileRepository;
@GetMapping
public ResponseEntity<Set<Profile>> searchProfiles(@RequestParam(value = "isMale", required = false) String isMaleVal,
@RequestParam(value = "heightMeters", required = false) String heightMetersVal,
@RequestParam(value = "weightKilos", required = false) String weightKilosVal,
@RequestParam(value = "dob", required = false) String dobVal) {
Integer isMaleVal;
BooleanCriteria isMaleCriteria;
if(isMaleVal != null) {
// Parse the value which could either be "0" for female, "1" for male or something like
// ?isMale={0,1} to indicate
// BooleanCriteria would store which values male, female or both) to include in the search
}
BigDecimal heighMeters;
BigDecimalCriteria heightCriteria;
if(heightMetersVal != null) {
// Parse the value which like in the examples could be something like:
// ?heightMeters={"gt" : "1.0"}
// BigDecimalCriteria stores range information
}
BigDecimal heighMeters;
BigDecimalCriteria weightCriteria;
if(weightKilosVal != null) {
// Parse the value which like in the examples could be something like:
// ?weightKilos={"eq" : "100.5"}
// BigDecimalCriteria stores range information
}
// Ditto for DOB and DateCriteria
// TODO: How to pack all of these "criteria" POJOs into a
// CrudRepository/JPQL query against the "profiles" table?
Set<Profile> profiles = profileRepository.searchProfiles(
isMaleCriteria, heightCriteria, weightCriteria, dobCriteria);
}
}
我对 BigDecimalCriteria
的想法是这样的:
// Basically it just stores the (validated) search criteria that comes in over the wire
// on the controller method
public class BigDecimalCriteria {
private BigDecimal lowerBound;
private Boolean lowerBoundInclusive;
private BigDecimal upperBound;
private Boolean upperBoundInclusive;
// Getters, setters, ctors, etc.
}
由于所有这些搜索条件都是可选的(因此可以是 null
),我被困在如何在 ProfileRepository
中编写 JPQL 查询:
public interface ProfileRepository extends CrudRepository<Profile,Long> {
@Query("???")
public Set<Profile> searchProfiles();
}
如何实现 @Query(...)
用于 ProfileRepository#searchProfiles
以启用我的所有搜索条件(给定所有允许的范围和要搜索的条件值),并允许任何条件为空/可选?
当然,如果有任何漂亮的小库或者 Spring Boot/JPA 已经有解决方案,我全都听好了!
原文由 smeeb 发布,翻译遵循 CC BY-SA 4.0 许可协议
可以通过spring data中的
JpaSpecificationExecutor
实现有规范的复杂查询。存储库接口必须扩展JpaSpecificationExecutor<T>
接口,因此我们可以通过创建新的Specification<T>
对象来指定数据库查询的条件。诀窍在于将规范接口与
JpaSpecificationExecutor
结合使用。这是示例:然后我们定义我们的存储库:
如您所见,我们扩展了另一个接口
JpaSpecificationExecutor
。该接口定义了通过规范类执行搜索的方法。我们现在要做的是定义我们的规范,它将返回
Predicate
包含查询的约束(在示例中PersonSpecification
正在执行查询 select * from person where name = ? 或 (姓氏 = ? 和年龄 = ?) ):现在是时候使用它了。下面的代码片段展示了如何使用我们刚刚创建的规范:
…
这 是github中的完整示例
您还可以使用规范创建任何复杂的查询