我目前正在使用Spring Boot和Spring Data JPA连接到oracle数据库。使用一个参数我只使用Spring Repository findById(Long id);
,它运行得很好。另一方面,搜索对我来说要复杂得多。在我们的例子中,用户提供了一个嵌套的JSON对象,其中包含多个可选的搜索参数(此时我无法改变它们通过嵌套JSON发送数据的方式)。这是JSON输入对象的样子:
{
"agent_filter": {
"first_name": "string",
"last_name": "string",
"agentNumber": "string",
"agentCode": "string"
},
"account": "string",
"status": "string",
"paid": "string",
"amount": "string",
"person_filter": {
"date_of_birth": "string",
"first_name": "string",
"last_name": "string",
"tax_id": "string"
}
}
所有搜索条件都是可选的(至少1个参数除外)
在后端,我们有以下实体:
@Entity
Account{
@OneToMany
List<PersonRole> role;
@OneToMany
List<AgentRole> role;
}
@Entity
PersonRole{
String role;
Person person;
}
@Entity
AgentRole{
String role;
Agent agent;
}
@Entity
Person{...}
@Entity
Agent{...}
因此,为了提供搜索功能,我可以进行多个连接。我开始使用带有@Query表示法的JPQL,但我必须对每个参数进行is null or
检查,这是一个很大的混乱。我开始研究其他选项,我看到了有关QueryDSL,标准,规范的内容,但我不确定应该关注和了解哪一个。不幸的是,我对这个问题并不了解很多,我希望有人可以指出我正确的方向,以便很好地实现这一搜索。谢谢!
答案 0 :(得分:2)
QueryDSL ftw!
当我遇到一个非常类似的问题时,让我举一个代码来举例说明我有一些我想要过滤的东西,其中很多都可以为空...
顺便说一句,如果你需要花哨的连接,那么你可能会直接使用查询dsl。这些示例适用于QueryDSL 3,因此您可能必须更改QueryDSL 4.因为您已经提到过如何“提供搜索功能,我可以执行多个连接”,您可能需要直接使用QueryDSL。
首先创建自己和BooleanBuilder,然后执行以下操作:
BooleanBuilder builder = new BooleanBuilder();
QContent content = QContent.content;
if (contentFilter.headlineFilter == null || contentFilter.headlineFilter.trim().length() == 0) {
// no filtering on headline as headline filter = null or blank
} else if (contentFilter.headlineFilter.equals(Filter.NULL_STRING)) {
// special case when you want to filter for specific null headline
builder.and(content.label.isNull());
} else {
try {
long parseLong = Long.parseLong(contentFilter.headlineFilter);
builder.and(content.id.eq(parseLong));
} catch (NumberFormatException e) {
builder.and(content.label.contains(contentFilter.headlineFilter));
}
}
if (contentFilter.toDate != null) {
builder.and(content.modifiedDate.loe(contentFilter.toDate));
}
if (contentFilter.fromDate != null) {
builder.and(content.modifiedDate.goe(contentFilter.fromDate));
}
因此,根据您是否拥有每个字段,您可以将其添加到过滤器中。
要使其工作,您将需要生成查询DSL元数据 - 这是使用com.mysema.query.apt.jpa.JPAAnnotationProcessor注释处理器完成的。它会在上面生成QContent.content。
那个BooleanBuilder是Predicate的子类。
答案 1 :(得分:1)
您需要使用自定义查询来创建自己的搜索查询。
@Query("select u from User u where u.firstname = :#{#customer.firstname}")
List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);
现在您可以根据需要添加任意数量的参数
答案 2 :(得分:1)
然而,使用查询dsl,条件,规范是一种很好的方法,但它需要学习它们。
您的问题只能通过JpaRepository解决。您的AccountRepository
可能会延长JpaRepository
,再次延伸QueryByExampleExecutor
。
QueryByExampleExecutor
提供了一些方法,例如findOne(Example<S> example)
和findAll(Example<S> example)
,它会根据您传递的Example
对象返回结果。
创建Example
很简单
Person person = new Person();
person.setFirstname("Dave");
Example<Person> example = Example.of(person);
这将匹配具有firstName = Dave