如何使用Spring JPA Repository按多个字段筛选实体?

huangapple go评论82阅读模式
英文:

How to filter an entity by multiple fields using a Spring JPA Repository?

问题

以下是翻译好的部分:

我正在为出租公寓的网页应用程序编写后端,但我不知道如何从数据库中筛选公寓(例如,可用房间、床铺、楼层或城市)。所以我有10个字段,用户可以在一次搜索中选择所有字段来筛选公寓,我只想把所有字段都放在一个JPA存储库方法中。但是,当我只使用其中的5个字段时,它开始冻结,我无法添加更多字段。当我开始输入例如"NumberOfRooms"时,它就会冻结,然后每输入一个字母也会冻结。

  1. 在搜索(筛选)字段方面是否有任何限制?

  2. 还有其他的做法吗?(我想把所有内容都放在一个方法中,在控制器中检查用户是否使用了所有筛选器,检查每个字段是否为null)

List<Flat> findAllByPriceBetweenAndCityAndRentORbuyAndUtilitiesBetweenAndNumberOfBedsBetweenAndNum(FastMoney less, FastMoney greater, String city, Boolean rentORbuy, int util1, int util2, int num1, int num2);
英文:

I am writing back-end for renting flat web app and I have no idea how to filter flats from database (ex. rooms available, beds,floor or city). So I have 10 fields , so user can choose all of them in one search to filter flats and I just to wanted put in JPA repository all fields in one method but when I used only 5 of them it started freezing I couldn't add more fields.When I start to type for example NumberOfRooms it's just froze ,then by typing each letter also freezing.

1.Is there any limit for searching(filtering) fields ?

2.What is another way to do that?( I wanted to put everything in one method and in controller check if user used all filters or not, checking each field for null)

List&lt;Flat&gt; findAllByPriceBetweenAndCityAndRentORbuyAndUtilitiesBetweenAndNumberOfBedsBetweenAndNum(FastMoney less,FastMoney greater,String city,Boolean rentORbuy,int util1,int util2,int num1,int num2);

答案1

得分: 17

88个字符的查询方法?拜托,不要!

为什么要编写一个88个字符的方法,它根本无法解析,当你可以编写一个格式良好的多行JPQL查询,使用文本块获取额外的分数?

为Spring Data仓库定制实现助攻!

如果你想要动态构建查询,使用Criteria API。你甚至可以从类型安全的元模型中受益。

所以,这是你需要做的:

  1. 前往Spring Data手册中的为Spring Data仓库创建定制实现部分,查看如何创建一个自定义仓库,在其中添加findFlats方法。
  2. 在新的findFlats方法内部,使用Criteria API来动态构建查询。

就是这样!

英文:

88-character query method? Please, don't!

Why would you write an 88-character method that's impossible to parse when you can write a nicely formatted multiline JPQL query, using Text Blocks for extra points?

Custom Implementations for Spring Data Repositories to the rescue!

If you want to build the query dynamically, use Criteria API. You can even benefit from the type-safe Metamodel.

So, here's what you need to do:

  1. Go to the Custom Implementations for Spring Data Repositories section in the Spring Data manual and see how to create a custom repository where you will add the findFlats method.
  2. Inside the new findFlats method use Criteria API to build the query dynamically.

That's it!

答案2

得分: 10

这里,由于您的用户并不总是提供您所需的所有字段,您需要使用更多的动态查询。我建议使用规范(Specifications)来实现最佳效果。

您可以在官方文档中找到更多信息:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

英文:

Here, since your user does not always provide all fields you need to use more Dynamic queries. I recommend Specifications as the best way to achieve it.

You can find more info in official documentation: https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

答案3

得分: 2

或许,与其拥有一个无尽命名的“find”方法(即使支持该方法),我建议为了提高可读性,创建一个自定义查询。另外,如果您想提高性能,甚至可以从查询中填充一个DTO,以避免从Jpa实体到DTO的映射(基本上我建议使用投影)。

在这里查看如何操作:https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

英文:

Maybe, rather than having a "find" method with an endless name (even if it is supported) I'd suggest, to improve the readability, to create a custom query. In addition if you want to speed the performance, you can even populate a DTO from the query in order to avoid mappings from your Jpa Entity to the DTO (basically I'm suggesting to use a Projection)

Check how to do it here https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

答案4

得分: -1

以下是翻译好的内容:

你还可以简单地使用像这样的库,它可以让你构建动态过滤器(支持逻辑运算符、比较运算符、枚举、日期、布尔值、连接、函数等等):https://github.com/turkraft/spring-filter

示例查询:

/search?filter= average(ratings) > 4.5 and brand.name in ('audi', 'land rover') and (year > 2018 or km < 50000) and color : 'white' and accidents is empty

用法:

@GetMapping(value = &quot;/search&quot;)
public List&lt;Entity&gt; search(@EntityFilter Specification&lt;Entity&gt; spec, Pageable page) {
  return repo.findAll(spec, page);
}

不要忘记添加依赖:

&lt;dependency&gt;
    &lt;groupId&gt;com.turkraft&lt;/groupId&gt;
    &lt;artifactId&gt;spring-filter&lt;/artifactId&gt;
    &lt;version&gt;0.9.5&lt;/version&gt;
&lt;/dependency&gt;

你还可以查看 rsql,虽然它现在有点过时了:https://github.com/jirutka/rsql-parser

英文:

You may also simply use a library like this one, which lets you build dynamic filters (supports logical operators, comparators, enums, dates, booleans, joins, functions, and much more): https://github.com/turkraft/spring-filter

Example query:
> /search?filter= average(ratings) > 4.5 and brand.name in ('audi', 'land rover') and (year > 2018 or km < 50000) and color : 'white' and accidents is empty

Usage:

@GetMapping(value = &quot;/search&quot;)
public List&lt;Entity&gt; search(@EntityFilter Specification&lt;Entity&gt; spec, Pageable page) {
  return repo.findAll(spec, page);
}

Don't forget the dependency:

&lt;dependency&gt;
    &lt;groupId&gt;com.turkraft&lt;/groupId&gt;
    &lt;artifactId&gt;spring-filter&lt;/artifactId&gt;
    &lt;version&gt;0.9.5&lt;/version&gt;
&lt;/dependency&gt;

You may also check rsql, although it's a bit outdated now https://github.com/jirutka/rsql-parser

huangapple
  • 本文由 发表于 2020年9月16日 19:40:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63919278.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定