如果我的术语不正确,请原谅。
我们使用Spring Data 、JpaRepositories和条件查询作为从数据库中查询数据的方法。
我遇到了一个问题,当我合并两个规范时,例如下面的代码示例中的hasCityAndTimeZone中的hasTimeZone和hasCity,它会对同一个表执行两次连接,因此下面的查询将类似于
select * from Staff, Location, Location
有没有办法让这两个规范使用相同的连接,而不是各自定义自己的本质上相同的连接?
对不起,代码可能不完整,我只是想展示一个快速的例子。
class Staff {
private Integer id;
private Location location;
}
class Location {
private Integer id;
private Integer timeZone;
private Integer city;
}
class StaffSpecs {
public static Specification<Staff> hasTimeZone(Integer timeZone) {
return new Specification<Staff>() {
@Override
public Predicate toPredicate(Root<Staff> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Integer> timeZonePath = root.join(Staff_.location).get(Location_.timeZone);
return cb.equal(timeZonePath, timeZone);
}
}
}
public static Specification<Staff> hasCity(Integer city) {
return new Specification<Staff>() {
@Override
public Predicate toPredicate(Root<Staff> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Integer> cityPath = root.join(Staff_.location).get(Location_.city);
return cb.equal(cityPath, city);
}
}
}
public static Specification<Staff> hasCityAndTimeZone(Integer city, Integer timeZone) {
return where(hasCity(city)).and(hasTimeZone(timeZone));
}
}
5条答案
按热度按时间hc2pp10m1#
不幸的是,没有现成的方法。Spring Data在内部使用
QueryUtils.getOrCreateJoin(…)
中的一些连接重用。您可以找出根上可能已经存在的连接,并在适当的地方重用它们:注意,只有当我们知道自己添加了哪些连接时,这才有效。当使用
Specifications
时,你也应该这样做,但我只是想确保没有人认为这是所有情况下的通用解决方案。3yhwsihp2#
根据@奥利弗的回答,我创建了
Specification
接口的扩展第1001章:我的JoinableSpecification.java
}
如何使用
gev0vcfq3#
在自定义规范中
....
....
vu8f3i0k4#
这是一个老问题,但我写了这个答案的人谁有这个问题。
我实现了一个通用方法来搜索连接别名,如果不存在具有此别名的连接,则它将创建具有给定pathFunction的连接。
正如奥利弗所说,您可以使用已定义连接,但如果您有一个实体的多个连接,则需要知道已定义连接的别名。
示例用法;
kg7wmglp5#
我稍微修改了实现,这样就不需要复制粘贴别名和函数
连接数据:
用法:
更新日期:
我做了一个小工具,使它更容易重用连接,在检查filter-dto字段是否为空时去掉“if”,并使用一个类型检查:
https://github.com/koval666/springspecwrapper