-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Optimize derived queries to avoid unnecessary JOINs for association ID access #3970
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
base: main
Are you sure you want to change the base?
Optimize derived queries to avoid unnecessary JOINs for association ID access #3970
Conversation
4543e07
to
6e1d918
Compare
This is similar to #3922. Now with the fixes in Hibernate in place we can continue with both pull requests. |
@mp911de Thank you for your review! I see that #3922 addresses the same issue. Would it be valuable to
Happy to collaborate or close this in favor of #3922 if that's preferred. |
Derived queries use a slightly different API that is however derived from Query utils basically duplicating code. We tried to use less JPA API to determine what we need to know for joining, especially that we use similar code for AOT processing where we have a limited metamodel.
Feel free to consolidate both variants into a single PR and introduce a better abstraction or design if you like.
Am 11. Aug. 2025, 16:34 +0200 schrieb Hyunjoon Park ***@***.***>:
… academey left a comment (spring-projects/spring-data-jpa#3970)
@mp911de Thank you for your review! I see that #3922 addresses the same issue.
I've reviewed their approach and noticed they modify QueryUtils directly, while my implementation focuses on JpqlUtils.
Would it be valuable to
1. Contribute my test cases to strengthen the validation?
2. Compare both approaches to see if there are complementary insights?
Happy to collaborate or close this in favor of #3922 if that's preferred.
Thanks
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Thank you for the clarification and the opportunity to improve the design! I understand that Derived queries and regular queries use different but duplicated code paths. There's a need to minimize JPA API usage for AOT processing. A unified abstraction would be beneficial I'll review #3922's approach and work on consolidating both solutions.
I'll update this PR with the consolidated solution. Thank you |
85e8de9
to
a93b17a
Compare
…D access This commit introduces an optimization that eliminates unnecessary JOINs when accessing association IDs in derived query methods. Changes: - Add PathOptimizationStrategy interface for query path optimization - Implement DefaultPathOptimizationStrategy using SingularAttribute.isId() - Create JpaMetamodelContext for AOT-compatible metamodel access - Update QueryUtils and JpqlUtils to use the unified optimization - Add comprehensive test coverage for the optimization The optimization detects patterns like findByAuthorId() and generates SQL that directly uses the foreign key column instead of creating a JOIN. This improves query performance with Hibernate 6.4+ where entity path traversal generates JOINs by default. Fixes spring-projects#3349 Signed-off-by: academey <[email protected]>
b522dd6
to
894a06c
Compare
- Add blank lines for better readability - Improve code formatting consistency Signed-off-by: academey <[email protected]>
Signed-off-by: Hyunjoon Park <[email protected]>
dc3b2de
to
14a380f
Compare
@mp911de I've completed the unified implementation as discussed. The key changes include
The implementation now provides a clean abstraction layer that can be extended for different optimization strategies while maintaining compatibility with AOT compilation. |
I'll review this later. For now, I see you skipped all my tests. |
@bukajsytlos Thank you for looking into this PR About the two test classes, I can see how they might look similar at first glance. ForeignKeyOptimizationIntegrationTests goes deeper and actually looks at the SQL being generated. It uses Hibernate's utilities to check that we're really avoiding the JOINs. So it's more like "does it work the way we intended?" I'm not sure which tests you're referring to as skipped, could you point me to specific ones? I tried to cover all the main scenarios, but I might have missed something from your previous work. Happy to add anything that's missing! The core idea from #3922 is definitely in here, just wrapped in a more extensible way with the strategy pattern. Let me know what you think needs more coverage. |
@academey all the composite id tests (EmbeddedId, IdClass) Regarding those differences, they test it from the same level of abstraction and are kind of misleading. |
@bukajsytlos You're absolutely right on both points. I think the right approach would be to like that
Would it make sense to consolidate everything into one test class like DerivedQueryOptimizationTests that covers all cases and properly verifies the SQL generation? I can refactor this based on your feedback. Thanks. |
Summary
This PR optimizes derived query methods to avoid unnecessary JOINs when accessing association IDs. The implementation consolidates approaches from both this PR and PR #3922 into a unified solution with improved abstraction.
Background
Starting from Hibernate 6.4.1, entity path traversal (e.g.,
author.id
) generates JOINs even when accessing only the ID field. This affects query performance and generates suboptimal SQL for common patterns likefindByAuthorId
.Solution
Unified Architecture
SingularAttribute.isId()
for reliable ID detectionImplementation
Examples
Before optimization:
After optimization:
Features
findByAuthorId
,countByProfileId
, etc.Testing
Performance Impact
This optimization eliminates unnecessary JOINs in common query patterns:
Compatibility
Fixes #3349