Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FluentQuery support to QuerydslPredicateExecutor and QueryByExampleExecutor #2421

Closed
wants to merge 3 commits into from

Conversation

mp911de
Copy link
Member

@mp911de mp911de commented Jul 28, 2021

FluentQuery allows extending a query specification initially defined by a Example probe or a Querydsl Predicate and fetching the actual result through a functional programming model:

interface PersonRepository extends QuerydslPredicateExecutor<Person> {
  <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}

PersonRepository repo = …;

List<PersonProjection> result = repo.findBy(QPerson.person.name.eq("Walter"), q -> q.sort(Sort.by("lastname")).as(PersonProjection.class).project("firstname", "lastname").all());

Stream<PersonProjection> result = repo.findBy(QPerson.person.name.eq("Walter"), FetchableFluentQuery::stream);

Closes #2228

…ExampleExecutor.

FluentQuery allows extending a query specification initially defined by a Example probe or a Querydsl Predicate and fetching the actual result through a functional programming model:

interface PersonRepository extends QuerydslPredicateExecutor<Person> {
  <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}

PersonRepository repo = …;

List<PersonProjection> result = repo.findBy(QPerson.person.name.eq("Walter"), q -> q.sort(Sort.by("lastname")).as(PersonProjection.class).all());
Copy link
Contributor

@michael-simons michael-simons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition in general seems nice, but I wonder why you don't default the methods and throw an UnsupportedOperationException ?

* @return all entities matching the given {@link Predicate}.
* @since 2.6
*/
<S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not defaulting it?

* @return all entities matching the given {@link Example}.
* @since 2.6
*/
<S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

@mp911de
Copy link
Member Author

mp911de commented Aug 11, 2021

This extension provides much more flexibility and is a pre-requisite to turn the other methods into default ones. We do not want to raise false expectations in terms of supported API to then throw an exception if e.g. streaming or projections aren't supported.

All default repository methods are invoked on the interface as we do not delicate these calls into the actual implementations.

@michael-simons
Copy link
Contributor

But the change here will break all other modules.
What if a module cant or wont implement them and adds just stub throwing an exception?

@michael-simons
Copy link
Contributor

Another option might be an additional FluentQuerydslPredicateExecutor ?

@mp911de
Copy link
Member Author

mp911de commented Aug 23, 2021

But the change here will break all other modules.
What if a module cant or wont implement them and adds just stub throwing an exception?

That's a consequence of the current arrangement. Modules can still throw an UnsupportedOperationException in that case.

Another option might be an additional FluentQuerydslPredicateExecutor ?

Introducing another set of interfaces (for imperative/reactive and Querydsl/Query-by-Example) break the concise programming model as the fluent method cannot be discovered from the marker interface that introduced Querydsl/Query-by-Example functionality to a repository. Each module would have to consider additional marker interfaces to contribute further fragments. As a consequence, we end up with a much more complex arrangement.

@michael-simons
Copy link
Contributor

That's a consequence of the current arrangement. Modules can still throw an UnsupportedOperationException in that case.

I don't understand this sentiment in connection with your original above:

We do not want to raise false expectations in terms of supported API to then throw an exception if e.g. streaming or projections aren't supported.

So either commons or a module will throw an exception and leave unfulfilled expectations. Doesn't make much sense to me.

Note that I am totally in for this new feature, but breaking all modules with the reasoning here doesn't work for me.

@michael-simons
Copy link
Contributor

Please add a note to the relevant FluentQuery.* interfaces that the builders are immutable in the sense that each step returning a FluentQuery.* again returns a complete new instance and does not modify the target.

Document that FluentQuery instances are immutable. Introduce oneValue/firstValue methods and turn one/first methods into methods returning Optional to simplify nullable method handling.
mp911de added a commit that referenced this pull request Oct 8, 2021
…ExampleExecutor.

FluentQuery allows extending a query specification initially defined by a Example probe or a Querydsl Predicate and fetching the actual result through a functional programming model:

interface PersonRepository extends QuerydslPredicateExecutor<Person> {
  <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}

PersonRepository repo = …;

List<PersonProjection> result = repo.findBy(QPerson.person.name.eq("Walter"), q -> q.sort(Sort.by("lastname")).as(PersonProjection.class).all());

Closes: #2228
Original pull request: #2421.
@mp911de mp911de added this to the 2.6 RC1 (2021.1.0) milestone Oct 8, 2021
@mp911de
Copy link
Member Author

mp911de commented Oct 8, 2021

That's merged now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for QueryDSL and Query by Example projections through a fluent API in repositories
3 participants