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

Support Single Query Loading for queries with where clauses #1617

Closed
wants to merge 9 commits into from

Conversation

schauder
Copy link
Contributor

This PR depends on #1615 and the branch currently actually includes those changes.

@schauder schauder requested a review from mp911de September 19, 2023 12:02
@schauder schauder force-pushed the issue/1601-where-clause branch from 45a1595 to b3759db Compare September 19, 2023 12:03
Copy link
Member

@mp911de mp911de left a comment

Choose a reason for hiding this comment

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

How far does Query work? Do we support top-level/embedded properties only or can we issue queries into one-to-one/map/list relations?

Other than that, left a few comments to address.

@@ -89,6 +96,35 @@ public Iterable<T> findAllById(Iterable<?> ids) {
return jdbcTemplate.query(sqlGenerator.findAllById(), Map.of("ids", convertedIds), this::extractAll);
}

public Iterable<T> findAllBy(Query query) {
Copy link
Member

Choose a reason for hiding this comment

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

findAll and others should be rewritten to use this method. I'm also not sure why we always return Iterable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Returning Iterable is kind of "inherited" from CrudRepository I guess.
How far should we go with switching to List? All the way up to SimpleJdbcRepository?
It could break inheritance for users extending one of the affected classes.
Although only in a mild way I guess, since of the few inheriting from one of the classes, very few will work with anything else than lists, I assume.

Copy link
Member

Choose a reason for hiding this comment

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

We should return List types in the Template API at least. Not everything needs to be used in the repository although almost all modules return List from their Simple…Repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Then let's just go all the way to SimpleRepository

Copy link
Member

Choose a reason for hiding this comment

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

I filed #1623 to keep track of that change.

@@ -28,5 +34,7 @@ public interface SqlGenerator {

String findAllById();

String findAllByCondition(BiFunction<Table, RelationalPersistentEntity, Condition> conditionSource);
Copy link
Member

Choose a reason for hiding this comment

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

The independence of SqlGenerator towards Condition is problematic as there is no control over binding order of parameters nor their names. Ideally, the creation of a statement returns something that encapsulates bindings and either the statement that can be rendered or the finally rendered statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think I understand what you are aiming for here.
The link between bind parameters and their values is controlled by the QueryMapper and therefore completely outside the SqlGenerator.

What would we achieve by dragging this into the SqlGenerator?

*
* @author Jens Schauder
*/
public class CombiningActiveProfileResolver implements ActiveProfilesResolver {
Copy link
Member

Choose a reason for hiding this comment

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

Probably easier to review once #1620 is merged and this PR is rebased on top of main.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The rebase is done.

ValueFunction<Object> valueFunction = (ValueFunction<Object>) criteria.getValue();
Object value = valueFunction.apply(getEscaper(comparator));

mappedValue = convertValue(comparator, value, propertyField.getTypeHint());
Copy link
Member

Choose a reason for hiding this comment

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

The conversion is entirely gone. Please reinstate conversion by wrapping ValueFunction in another function that applies convertValue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There really never was a conversion. ValueFunction is always a ValueFunction<String> obtained using toString of whatever was passed in as an argument. It also should only be converted to String since it is used in LIKE expressions and nothing else.

I therefore don't really consider removing the call to the converter a problem.
Although I also agree, that we should probably implement proper conversion, instead of just calling toString. And maybe at the same time at least warn, when LIKE is used with a non String property.
But I'd rather do that in a separate issue.
What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

One is how it is used. The other is the concept of abstractions. Moving such parts out of sight easily breaks the conceptual flow and then we end up with code that we don't understand. I also think that we have areas in our code that require much more cleanup than this one.

And maybe at the same time at least warn, when LIKE is used with a non String property.

I do not agree. One can have an Enum property and run a LIKE query handing in a String value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I introduced conversion of ValueFunction in the correct order: first conversion, than escaping, for both JDBC and R2DBC.

@schauder
Copy link
Contributor Author

How far does Query work? Do we support top-level/embedded properties only or can we issue queries into one-to-one/map/list relations?

Queries beyond those based on the top-level class are and will only be supported for Single Query Loading as long as they are formulated as
exists <subselect> or <id> in <subselect> constructs.

We currently don't support deep predicates for the default query strategy either.

@schauder schauder force-pushed the issue/1601-where-clause branch from b3759db to 8fe6fda Compare September 25, 2023 11:13
@mp911de mp911de added the type: enhancement A general enhancement label Sep 26, 2023
@mp911de
Copy link
Member

mp911de commented Sep 26, 2023

exists or in constructs.
We currently don't support deep predicates for the default query strategy either.

Asking users to run a id IN <subselect> for a query that dives into a relation (one-to-one/one-to-many) is a too high barrier when using Where queries. While it can be a temporary solution, we should translate Where predicates pointing at relationships into proper exists/IN queries.

Simplify ValueFunction mapping. Remove invariants of findBy SQL generation in favor of the Condition-based variant. Reduce visibility.
@schauder
Copy link
Contributor Author

While it can be a temporary solution, we should translate Where predicates pointing at relationships into proper exists/IN queries.

I agree, but think we might have to rethink the abstraction level on which Query is operating. Currently it is just a thin layer over SQL. But we might have to go to proper aggregate support as well.

mp911de pushed a commit that referenced this pull request Sep 26, 2023
mp911de pushed a commit that referenced this pull request Sep 26, 2023
mp911de pushed a commit that referenced this pull request Sep 26, 2023
Simplify ValueFunction mapping. Remove invariants of findBy SQL generation in favor of the Condition-based variant. Reduce visibility. Change return value of AggregateReader to List

See #1601
Original pull request: #1617
mp911de added a commit that referenced this pull request Sep 26, 2023
mp911de added a commit that referenced this pull request Sep 26, 2023
Simplify type and interface arrangement.

See #1601
Original pull request: #1617
@mp911de mp911de added this to the 3.2 RC1 (2023.1.0) milestone Sep 26, 2023
@mp911de
Copy link
Member

mp911de commented Sep 26, 2023

That's merged now.

@mp911de mp911de closed this Sep 26, 2023
@mp911de mp911de deleted the issue/1601-where-clause branch September 26, 2023 12:42
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.

Support Single Query Loading for template methods with arbitrary where clauses
2 participants