我有不同的规范类别:
public class UserSpecification implements Specification<ApplicationUser> {
private SearchCriteria criteria;
public UserSpecification(SearchCriteria criteria) {
this.criteria = criteria;
}
@SuppressWarnings("unchecked")
@Override
public Predicate toPredicate(Root<ApplicationUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
...
}
}
public class HotelSpecification implements Specification<Hotel> {
private SearchCriteria criteria;
public HotelSpecification(SearchCriteria criteria) {
this.criteria = criteria;
}
@SuppressWarnings("unchecked")
@Override
public Predicate toPredicate(Root<Hotel> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
...
}
}
所以我尝试使用通用构建器来组成相同类型的规范,因为构建器类是99%重复的类,只是类类型不同。
public class MySpecificationBuilder {
private final List<SearchCriteria> params;
public MySpecificationBuilder () {
params = new ArrayList<>();
}
public MySpecificationBuilder with(String key, String value) {
params.add(new SearchCriteria(key, value));
return this;
}
public Specification<?> build() {
if (params.size() == 0) {
return null;
}
List<Specification<?>> specs = new ArrayList<>();
for (SearchCriteria param : params) {
specs.add(new UserSpecification(param)); //how to make here generic
}
Specification<?> result = specs.get(0);
for (int i = 1; i < specs.size(); i++) {
result = Specification.where(result).and(specs.get(i)); //warning 1
}
return result;
}
}
我想知道是否鼓励/可以使用通用规范构建器。如果是这样,如何为不同的规格创建通用生成器?
答案 0 :(得分:1)
如果我正确理解了您的目标,则应该可以执行以下操作。
public <T> Specification<T> build(Function<SearchCriteria, Specification<T>> mappingToSpecification) {
if (params.size() == 0) {
return null;
}
List<Specification<T>> specs = new ArrayList<>();
for (SearchCriteria param : params) {
specs.add(mappingToSpecification.apply(param)); //how to make here generic
}
Specification<T> result = specs.get(0);
for (int i = 1; i < specs.size(); i++) {
result = Specification.where(result).and(specs.get(i)); //warning 1
}
return result;
}
build
方法具有类型参数,使您可以将其用于不同的类型,例如:
// Assumes builder.with has been called previously
builder.build(
searchCriteria -> new MyObjectSpecification((SearchCriteria) searchCriteria)
);
答案 1 :(得分:0)
公共类GenericSpecificationBuilder {
private final List<SearchCriteria> params;
public GenericSpecificationBuilder() {
params = new ArrayList<SearchCriteria>();
}
public GenericSpecificationBuilder with(String key, String operation, Object value,String perdicateType) {
params.add(new SearchCriteria(key, operation, value, perdicateType));
return this;
}
public Specification<T> build() {
if (params.size() == 0) {
return null;
}
List<Specification> specs = params.stream()
.map(x -> getSpecification(x))
.collect(Collectors.toList());
Specification result = specs.get(0);
for (int i = 1; i < params.size(); i++) {
System.out.println(params.get(i)
.isOrPredicate()
);
result = params.get(i-1)
.isOrPredicate()
? Specification.where(result)
.or(specs.get(i))
: Specification.where(result)
.and(specs.get(i));
}
return result;
}
public Specification<T> getSpecification(SearchCriteria criteria) {
Specification<T> specification = new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Predicate predicate = genericCriteria(criteria,root,criteriaBuilder);
return predicate;
}
};
return specification;
}
public Predicate genericCriteria(SearchCriteria criteria, Root<?> root, CriteriaBuilder builder){
if (criteria.getOperation().equalsIgnoreCase(">")) {
return builder.greaterThanOrEqualTo(
root.<String> get(criteria.getKey()), criteria.getValue().toString());
}
else if (criteria.getOperation().equalsIgnoreCase("<")) {
return builder.lessThanOrEqualTo(
root.<String> get(criteria.getKey()), criteria.getValue().toString());
}
else if (criteria.getOperation().equalsIgnoreCase(":")) {
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(
root.<String>get(criteria.getKey()), "%" + criteria.getValue() + "%");
} else {
return builder.equal(root.get(criteria.getKey()), criteria.getValue());
}
}
return null;
}
}
这样,除非您想限制某个实体的某些操作,否则不必为每个实体创建Specification的单独实现。