It is necessary to sort the table data (ORDER BY) on the frontend. Now requests to the database (PostgreSQL) are made using @Query annotations. There are 5 columns in the table, and I don’t want to do a lot of @Query for each column in the table, how to create a query in the database dynamically, so that the frontend would specify what needs to be sorted?
2 answers
Use PagingAndSortingRepository and transfer to Sort in repository methods.
- Getting the
ListfromPageeasiest with the getContent () method. But when calling a method withSort,Iterableshould be returned, notPage. - Sergey Gornostaev - and the filter (Like) can be done in this way? - user9046477
- Yes, you can :
discontCardRepository.findBySomeFieldLike(sort)- Sergey Gornostaev - and key = value? That frontend itself specified columns and values? - user9046477
- Yeah, I forgot, after
sortsecond parameter values forsomeFieldmust be specified. - Sergey Gornostaev
The easiest, most convenient and flexible option, in my opinion, is to use the QueryDSL extensions and Web support . Out of the box we get dynamic filtering, with support for sorting and pagination!
First you need to connect QueryDSL to the project:
<dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> </dependency> <build> <plugins> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/annotations</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> </plugins> </build> Then you need to compile the project to create Q-files for the entities (for example, mvn compile ).
After, create a repo, inheriting, including, from QueryDslPredicateExecutor and, optionally, from QuerydslBinderCustomizer, for example:
interface MyEntityRepo extends JpaRepository<MyEntity, Long>, QueryDslPredicateExecutor<MyEntity>, QuerydslBinderCustomizer<MyEntity> { } If the project uses Spring Data REST , you can immediately use such queries:
/myEntities?field1=value1&field2=value2&sort=field2,desc&size=10&page=2 If you need to create your controller, this is done, for example, as follows:
@RestController @RequestMapping("/myEntities") public class ProfileController { @Autowired private MyEntityRepo repo; @GetMapping public ResponseEntity<?> getAll(@QuerydslPredicate(root = MyEntity.class, bindings = MyEntityRepo.class) Predicate predicate, Pageable pageable) { Page<MyEntity> entities = repo.findAll(predicate, pageable); return ResponseEntity.ok(entities); } } To customize the filter, you must use the customize QuerydslBinderCustomizer method a:
public interface MyEntityRepo extends JpaRepository<MyEntity, Long>, QueryDslPredicateExecutor<MyEntity>, QuerydslBinderCustomizer<QMyEntity> { @Override default void customize(QuerydslBindings bindings, QMyEntity entity) { bindings.excluding( // исключаем не нужные поля из фильтра entity.id, entity.version, // ... ); // реализуем фильтр between по полую field1 bindings.bind(entity.field1).all((path, value) -> { Iterator<? extends Integer> it = value.iterator(); Integer from = it.next(); if (value.size() >= 2) { Integer to = it.next(); return path.between(from, to)); // between: если поле field1 указано в строке запроса два раза } else { return path.goe(from); // greter than: если поле field1 указано один раз } }); // фильтр like по полю field2 bindings.bind(entity.field2).first(StringExpression::containsIgnoreCase); } }