我正在创建一个REST服务,它将允许我提供所有对象或筛选后的子集。我的界面基于我无法更改的设计。
到目前为止:使用Spring我已经创建了控制器:
@RequestMapping(path = "/designs", method = GET)
public ResponseEntity<CommonResponse> getDesigns(
@RequestHeader(name = "authenticationToken", required = AUTHENTICATION_TOKEN_REQUIRED) String authenticationToken
, @RequestParam(name = "title", required = false) String title
, @RequestParam(name = "designCategory", required = false) String designCategory
, @RequestParam(name = "epic", required = false) String epic
) {
return designService.get(title, designCategory, epic);
}
服务:
@Transactional
@Override
public ResponseEntity<CommonResponse> get(String title, String designCategory, String epic) {
try {
if(title == null && designCategory == null && epic == null) {
commonResponse.setDesigns(designRepository.findAll());
} else {
commonResponse.setDesigns(designRepository.findByTitleAndDesignCategoryAndJiraEpicNumber(title, designCategory, epic));
}
checkForNoResults(commonResponse.getDesigns());
} catch (NoResultsFoundException e) {
return ResponseEntity.status(e.getStatus()).body(e.getResponse());
}
return ResponseEntity.ok(commonResponse);
}
模型:
@Entity(name = "design")
public class DesignModel extends BaseModel {
@Column
private String title;
@Column
private LocalDate createdDate;
@Column
private LocalDate updatedDate;
@OneToOne
@JoinColumn(name = "design_category_id")
private DesignCategoryModel designCategory;
@Column
private String documentUrl;
@Column
private String featureHomeUrl;
@Column
private String jiraEpicNumber;
@Column
private String description;
//Getters and setters... etc.
}
还有一个存储库:
@Repository
public interface DesignRepository extends CrudRepository<DesignModel, Integer> {
ArrayList<DesignModel> findAll();
ArrayList<DesignModel> findByTitleAndDesignCategoryAndJiraEpicNumber(String title, String designCategory, String epic);
}
这很好,但是:
如果我只想按标题过滤,不提供其他值,则我的查询什么也不提供。我在这里简要查看了CriteriaBuilder:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
但是,我需要访问我的会话对象才能创建CriteraBuilder(并且鉴于我从未创建过HibernateUtils类,因此我无法获取会话)。
如何创建这些“条件条件”?
答案 0 :(得分:0)
这看起来应该很简单,就像您需要使用谓词和Querydsl
https://www.baeldung.com/rest-api-search-language-spring-data-querydsl
但是这是基础知识
设置您的后继地位以接受PredicateExecutor
public interface MyUserRepository extends JpaRepository<MyUser, Long>,
QuerydslPredicateExecutor<MyUser>, QuerydslBinderCustomizer<QMyUser> {
@Override
default public void customize(
QuerydslBindings bindings, QMyUser root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
bindings.excluding(root.email);
}
}
然后一个客户谓词获取您的参数列表
ublic class MyUserPredicate {
private SearchCriteria criteria;
public BooleanExpression getPredicate() {
PathBuilder<MyUser> entityPath = new PathBuilder<>(MyUser.class, "user");
if (isNumeric(criteria.getValue().toString())) {
NumberPath<Integer> path = entityPath.getNumber(criteria.getKey(), Integer.class);
int value = Integer.parseInt(criteria.getValue().toString());
switch (criteria.getOperation()) {
case ":":
return path.eq(value);
case ">":
return path.goe(value);
case "<":
return path.loe(value);
}
}
else {
StringPath path = entityPath.getString(criteria.getKey());
if (criteria.getOperation().equalsIgnoreCase(":")) {
return path.containsIgnoreCase(criteria.getValue().toString());
}
}
return null;
}
}
将它们封装在SearchCriteria中
public class SearchCriteria {
private String key;
private String operation;
private Object value;
}
最后,您需要一个构建器来实际动态创建您的条件
public class MyUserPredicatesBuilder {
private List<SearchCriteria> params;
public MyUserPredicatesBuilder() {
params = new ArrayList<>();
}
public MyUserPredicatesBuilder with(
String key, String operation, Object value) {
params.add(new SearchCriteria(key, operation, value));
return this;
}
public BooleanExpression build() {
if (params.size() == 0) {
return null;
}
List predicates = params.stream().map(param -> {
MyUserPredicate predicate = new MyUserPredicate(param);
return predicate.getPredicate();
}).filter(Objects::nonNull).collect(Collectors.toList());
BooleanExpression result = Expressions.asBoolean(true).isTrue();
for (BooleanExpression predicate : predicates) {
result = result.and(predicate);
}
return result;
}
}
这里有控制器示例-您需要对其进行调整,因为这不是REST的,但是有点时髦
@Controller
公共类UserController {
@Autowired
private MyUserRepository myUserRepository;
@RequestMapping(method = RequestMethod.GET, value = "/myusers")
@ResponseBody
public Iterable<MyUser> search(@RequestParam(value = "search") String search) {
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
if (search != null) {
Pattern pattern = Pattern.compile("(\w+?)(:|<|>)(\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
}
BooleanExpression exp = builder.build();
return myUserRepository.findAll(exp);
}
}