简体   繁体   English

如何使用 Spring JPA 存储库按多个字段过滤实体?

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

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.所以我有 10 个字段,所以用户可以在一次搜索中选择所有字段来过滤平面,我只是想以一种方法将所有字段放入 JPA 存储库,但是当我只使用其中的 5 个时,它开始冻结,我无法添加更多字段。当我开始输入例如 NumberOfRooms 时,它只是冻结,然后输入每个字母也冻结。

1.Is there any limit for searching(filtering) fields ? 1.搜索(过滤)字段有限制吗?

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) 2.还有什么方法可以做到这一点?(我想把所有东西都放在一个方法中,并在控制器中检查用户是否使用了所有过滤器,检查每个字段是否为空)

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

88-character query method? 88个字符的查询方法? 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?当您可以编写格式良好的多行 JPQL 查询并使用Text Blocks获得额外的分数时,为什么还要编写一个无法解析的 88 个字符的方法?

Custom Implementations for Spring Data Repositories to the rescue! Spring Data Repositories 的自定义实现来拯救你!

If you want to build the query dynamically, use Criteria API.如果要动态构建查询,请使用 Criteria API。 You can even benefit from the type-safe Metamodel .您甚至可以从类型安全的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.转到 Spring Data 手册中的Spring Data Repositories 自定义实现部分,了解如何创建自定义存储库,您将在其中添加findFlats方法。
  2. Inside the new findFlats method use Criteria API to build the query dynamically.在新的findFlats方法中,使用 Criteria API 动态构建查询。

That's it!就是这样!

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

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)此外,如果您想提高性能,您甚至可以从查询中填充 DTO,以避免从 Jpa 实体映射到 DTO(基本上我建议使用投影)

Check how to do it here https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/在此处查看如何操作https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

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您也可以简单地使用这样的库,它可以让您构建动态过滤器(支持逻辑运算符、比较器、枚举、日期、布尔值、连接、函数等等): https : //github.com/turkraft/spring -筛选

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

Usage:用法:

@GetMapping(value = "/search")
public List<Entity> search(@EntityFilter Specification<Entity> spec, Pageable page) {
  return repo.findAll(spec, page);
}

Don't forget the dependency:不要忘记依赖:

<dependency>
    <groupId>com.turkraft</groupId>
    <artifactId>spring-filter</artifactId>
    <version>0.9.5</version>
</dependency>

You may also check rsql, although it's a bit outdated now https://github.com/jirutka/rsql-parser您也可以检查 rsql,虽然它现在有点过时了https://github.com/jirutka/rsql-parser

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM