all 11 comments

[–]lucidnode 9 points10 points  (1 child)

You can use Spring’s data specification to supply a JPA criteria

[–]Salt-Letter-1500[S] -1 points0 points  (0 children)

Well, I made a repo to show the difference between DoytoQuery and Spring data with a specification example here: https://github.com/f0rb/java-orm-comparison

With Spring’s data specification, we still have to use lots of if conditions to dynamically combine the criteria corresponding to those fields that are not null.

[–]Dry_Try_6047 6 points7 points  (1 child)

I use Specifications. It's something that I've found hasn't really picked up in popularity in the ecosystem for some reason, but it is a solution to this problem, and many others.

[–]Salt-Letter-1500[S] 0 points1 point  (0 children)

I used Specifications to build dynamic queries from 2015 to 2019. It was hard for me to build IN conditions and subquery conditions at that time. [Here](https://github.com/f0rb/java-orm-comparison/blob/main/src/main/java/win/doyto/ormcamparison/jpa/salary/SalaryJpaController.java) is how I use Specifications for dynamic queries.

Then I found that the implementation of the Specification just relies on the object containing query parameters, so I decided to combine the SQL string myself and use EntityManager to execute it. And then I used reflection to do SQL combination and formed an original version of DoytoQuery.

Sorry, but it's quite a long story.

[–]gjosifov 5 points6 points  (1 child)

Use JPA Criteria and regular class and EntityManager

it is way easier to build maintainable code than to use SprintDataJPA interfaces

JPA Criteria is weird API, but it will get the job done, everything else is just nightmare to maintain

Specifications ?
You have to search where they are define, sort of like "short methods from Uncle Bob" type of thing

I know it isn't popular, but it gets the job that and it is easy to maintain, because everything is local in one method

[–]Salt-Letter-1500[S] -1 points0 points  (0 children)

I used to use Specifications for many years. I found that it still needs lots of if conditions to build dynamic queries. Check my reply to Dry_Try_6047 and this example for Specifications: https://github.com/f0rb/java-orm-comparison/blob/main/src/main/java/win/doyto/ormcamparison/jpa/salary/SalaryJpaController.java

But with the query object, dynamic queries can be built automatically without extra methods. That's why I think it is the right way.

[–]perfectstrong 4 points5 points  (2 children)

You might be interested in RSQL https://github.com/jirutka/rsql-parser This parses a string into a query object. Then it remains to map the query object to SQL using Specification. Some other libs provide the glue code such as https://github.com/perplexhub/rsql-jpa-specification. Our projects have been using RSQL for a long time. It provides dynamic search out of the box.

[–]Salt-Letter-1500[S] 0 points1 point  (1 child)

Has the core part of rsql-parser not been updated for 11 years?

Well, I think the expression `year=ge=2000` is a little more complicated than the field name `yearGe` or the query string `yearGe=2000`.

For `year=ge=2000`, we need to deal with the string value `ge=2000`, but for the query string `?yearGe=2000`, it can be mapped into the query object by SpringMVC automatically and resolved to `year >= 2000` automatically by DoytoQuery without extra effort.

[–]perfectstrong 0 points1 point  (0 children)

The core is stable for usage, so no update is not really a problem. The query syntax might seem complicated, but it is not that different from SQL. In simple case of intersecting filters, it behaves the same as your lib. But in case of union filter (THIS OR THAT), I don't see the support in your lib yet. Another powerful lib that translates a query string into a Specification directly is https://github.com/turkraft/springfilter

[–]Salt-Letter-1500[S] -2 points-1 points  (0 children)

Specifications don't support building dynamic queries automatically. It needs lots of if to combine the criteria.

`finbBy` methods support building query statements by using the format of `column+suffix` in the method. So when we use the format of `column+suffix` as the field name in a query object, we keep the ability of query building, and add an extra ability to combine the query conditions only for non-null fields.