Skip to content

Query method parameter of type Class erroneously considered dynamic projection parameter #2770

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

Closed
odrotbohm opened this issue Jan 31, 2023 · 1 comment
Assignees
Labels
type: enhancement A general enhancement

Comments

@odrotbohm
Copy link
Member

Consider a repository query method declaration like this:

interface SomeRepository extends Repository<SomeAggregate, …> {

  @Query("some query using `type` as parameter")
  <T extends SomeAggregate> Collection<T> findOnlySpecificSubTypes(Class<T> type);
}

The query method intends to find only subtypes of SomeAggregate and the type being defined by the type parameter. Unfortunately, it is currently always considered a dynamic projection parameter, even if we are not dealing with a projection here.

The decision whether a parameter is considered a dynamic projection one is currently held in Parameter which as of now, unfortunately, doesn't know anything about the primary aggregate type. If it had that, we could back out of any projection considerations once we realize the Class' component type is tied to that.

A different approach could be to disregard a Class parameter annotated with @Param as projection parameter. The annotation currently requires a value to be set, which makes it a bit cumbersome to use, as you'd need to repeat the parameter name unconditionally. I am not sure whether making that optional would be a big issue.

@odrotbohm
Copy link
Member Author

After a brief discussion with @mp911de we decided it would be feasible to hand the aggregate type into the creation call chain of the Parameters instances. We can implement this in a backwards-compatible way so that we wouldn't break store modules but get them onto the new API eventually. A spike incorporating Commons and JPA seems to validate the feasibility.

The support for @Param could be added as a mitigating measure and less invasive fix for the 2.x branch, with a deprecation of that support added in 3.1.

odrotbohm added a commit that referenced this issue Feb 1, 2023
To support the binding of Class parameters to queries for declared query methods, we have to be able to differentiate them from Class parameters that are supposed to represent projections. We can do that by relating the declared Class' element type to the aggregate root type as a Class typed to that or any subtype of it will never trigger a projection by definition.

So far the Parameter(s) abstraction was solely created from a query method's Method. We now changed that for QueryMethod to forward the aggregate type detected on the RepositoryMetadata and consider it during the detection of dynamic projection parameters.

As a mitigating measure, we now also support @param on Class-typed parameters to explicitly mark them for query binding. This is primarily to be able to add this support to the 2.7

The changes are built in a way that modules extending that mechanism will continue to work as is but see deprecation warnings on methods and constructors involved. Adapting extending code to the new APIs will automatically enable the support for bindable Class parameters on query methods.

Fixes #2770.
odrotbohm added a commit that referenced this issue Feb 1, 2023
…ection parameters.

This is a 2.7.x adapted fix for #1452 (the actual fix for 3.x contained in #2770). We temporarily support the use of @param on Class parameters to allow them to be be used as actual query parameters.

On 3.0.x the general parameter handling gets smarter so that this mitigation can be phased out pretty quickly, but this here seems to be a simple enough fix for those who cannot upgrade to 3.0 any time soon.

Fixes #1452.
odrotbohm added a commit that referenced this issue Feb 1, 2023
To support the binding of Class parameters to queries for declared query methods, we have to be able to differentiate them from Class parameters that are supposed to represent projections. We can do that by relating the declared Class' element type to the aggregate root type as a Class typed to that or any subtype of it will never trigger a projection by definition.

So far the Parameter(s) abstraction was solely created from a query method's Method. We now changed that for QueryMethod to forward the aggregate type detected on the RepositoryMetadata and consider it during the detection of dynamic projection parameters.

As a mitigating measure, we now also support @param on Class-typed parameters to explicitly mark them for query binding. This is primarily to be able to add this support to the 2.7

The changes are built in a way that modules extending that mechanism will continue to work as is but see deprecation warnings on methods and constructors involved. Adapting extending code to the new APIs will automatically enable the support for bindable Class parameters on query methods.

Fixes #2770.
@mp911de mp911de added the type: enhancement A general enhancement label Feb 14, 2023
@mp911de mp911de added this to the 2.7.8 (2021.2.8) milestone Feb 14, 2023
mp911de added a commit that referenced this issue Feb 14, 2023
Use consistently domain type instead of introducing a new terminology to repository infrastructure.

Rename Kotlin variant of ParameterUnitTests to KParameterUnitTests to avoid duplicate classes.

See #2770
Original pull request: #2771
mp911de pushed a commit that referenced this issue Feb 14, 2023
To support the binding of Class parameters to queries for declared query methods, we have to be able to differentiate them from Class parameters that are supposed to represent projections. We can do that by relating the declared Class' element type to the aggregate root type as a Class typed to that or any subtype of it will never trigger a projection by definition.

So far the Parameter(s) abstraction was solely created from a query method's Method. We now changed that for QueryMethod to forward the aggregate type detected on the RepositoryMetadata and consider it during the detection of dynamic projection parameters.

As a mitigating measure, we now also support @param on Class-typed parameters to explicitly mark them for query binding. This is primarily to be able to add this support to the 2.7

The changes are built in a way that modules extending that mechanism will continue to work as is but with the intent to deprecate the previous API. Adapting extending code to the new APIs will automatically enable the support for bindable Class parameters on query methods.

Fixes #2770.
Original pull request: #2771
mp911de added a commit that referenced this issue Feb 14, 2023
Use consistently domain type instead of introducing a new terminology to repository infrastructure.

Rename Kotlin variant of ParameterUnitTests to KParameterUnitTests to avoid duplicate classes.

See #2770
Original pull request: #2771
mp911de pushed a commit that referenced this issue Feb 14, 2023
…ojection parameters.

This is a 2.7.x adapted fix for #1452 (the actual fix for 3.x contained in #2770). We temporarily support the use of @param on Class parameters to allow them to be be used as actual query parameters.

On 3.0.x the general parameter handling gets smarter so that this mitigation can be phased out pretty quickly, but this here seems to be a simple enough fix for those who cannot upgrade to 3.0 any time soon.

Closes #2770.
See #1452.
Original pull request: #2772
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment