在 spring data jpa 存储库中搜索许多可选参数
Posted
技术标签:
【中文标题】在 spring data jpa 存储库中搜索许多可选参数【英文标题】:Search by many optional parameters in spring data jpa repository 【发布时间】:2020-02-03 00:08:50 【问题描述】:所以我有表格评论和作者。我想用许多可选参数构建复杂的搜索栏。我想要过滤带有可选作者名字/姓氏的 cmets 和一些标志,如受欢迎程度(基于评论评级)。
由于我不知道如何使用 spring data jpa 存储库编写它,我一直在考虑将其编写为带有 @Query 注释的本机查询,这样应该可以工作
Select c.* from comment c join author a on a.id = c.author_id
Where (:firstname = '' or (:firstname = a.firstname))
And (:lastname = '' or (:lastname = a.lastname))
And (:popular = false or (c.rating > 25))
是否可以选择使用 spring data jpa 编写它?
例如,将来我计划添加更多参数和分页。使用spring它会像1分钟的sql查询我会失去几个小时。
在这种情况下有一些最佳做法吗?
【问题讨论】:
我认为,这并没有那么复杂。提供所需的实体类,需要查看这些类之间的关系 将来我会添加 10 多个条件时会很复杂。然后 Spring 方法将像 100 个字符或更多。我的域不是那么直观,所以我切换到评论/作者。所以让我们假设评论可以有很多作者(愚蠢的是)。评论有具有@OneToMany 关系的字段作者我稍后会更改代码 【参考方案1】:我建议使用JpaSpecificationExecutor
存储库方法findAll(Specification<T> spec, Pageable pageable)
。此解决方案允许您使用相同的存储库和服务 API 扩展参数列表
实体:
@Entity
@Table(name = "author")
public class Author
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@Column(name = "firstname")
String firstname ;
@Column(name = "lastname")
String lastname ;
// getters, setters, equals, hashcode, toString ...
@Entity
@Table(name = "comment")
public class Comment
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@ManyToOne
@JoinColumn(name = "author_id")
Author author;
@Column(name = "rating")
Integer rating;
// getters, setters, equals, hashcode, toString ...
存储库:
@Repository
public interface CommentRepository
extends JpaRepository<Comment, Long>, JpaSpecificationExecutor<Comment>
规格: org.springframework.data.jpa.domain.Specification
public class CommentSpecs
/** if firstname == null then specification is ignored */
public static Specification<Comment> authorFirstnameEquals(String firstname)
return (root, query, builder) ->
firstname == null ?
builder.conjunction() :
builder.equal(root.get("author").get("firstname"), firstname);
/** if lastname == null then specification is ignored */
public static Specification<Comment> authorLastnameEquals(String lastname)
return (root, query, builder) ->
lastname == null ?
builder.conjunction() :
builder.equal(root.get("author").get("lastname"), lastname);
/** if rating == null then specification is ignored */
public static Specification<Comment> ratingGreaterThan(Integer rating)
return (root, query, builder) ->
rating == null ?
builder.conjunction() :
builder.greaterThan(root.get("rating"), rating);
服务方法参数:
public class CommentParameters
String authorFirstname;
String authorLastname;
Integer rating;
// getters, setters
所有参数都可以为空。您可以只设置您需要的参数。如果参数为空,我们的规范将忽略它
服务:
@Service
public class CommentService
@Autowired
CommentRepository repository;
public List<Comment> getComments(CommentParameters params, Pageable pageable)
Specification spec1 = CommentSpecs.authorFirstnameEquals(params.getAuthorFirstname());
Specification spec2 = CommentSpecs.authorLastnameEquals(params.getAuthorLastname());
Specification spec3 = CommentSpecs.ratingGreaterThan(params.getRating());
Specification spec = Specifications.where(spec1).or(spec2).or(spec3);
return repository.findAll(spec, pageable);
我使用文本编辑器编写了代码,因此需要对其进行修订。但我认为重点很容易发现
【讨论】:
我会从上面的答案中测试解决方案,因为没有那么多样板,然后我会测试你的 没有一个优雅的解决方案,使用单个文本查询进行多个可选参数搜索。所有静态查询解决方案都将更难以理解,但可维护性和可读性较差【参考方案2】:你可以使用jpa或者criteriabuilder,如果你更喜欢使用JPA,你可以这样做:
@Query("select s from SomeEntity s "
+ "where (s.description is null or s.description = :description) "
+ "and (s.name is null or s.name = :name) "
List<SomeEntity> find(String description, String name);
【讨论】:
如何从 spring data jpa 为您的示例启用分页? 只需添加参数Pageable pageable
,有点像Page<SomeEntity> find(String description, String name, Pageable pageable);
。 Jpa 会解决剩下的问题
是的。没问题以上是关于在 spring data jpa 存储库中搜索许多可选参数的主要内容,如果未能解决你的问题,请参考以下文章
为什么Spring-Data-JPA Async无法正常工作?
没有 Spring Boot 的 Spring Data JPA