Skip to content

Add support for subquery modifiers (LIMIT/OFFSET) in Hibernate #1304

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

Merged
merged 5 commits into from
Aug 14, 2025

Conversation

DongGunYoon
Copy link
Contributor

@DongGunYoon DongGunYoon commented Aug 1, 2025

Description

This PR addresses a long-standing limitation in QueryDSL where LIMIT and OFFSET modifiers were ignored when used within subqueries. This change enables full subquery modifier support specifically for Hibernate users while maintaining backward compatibility and JPQL standard compliance for other JPA providers.

Related Issue: This resolves the subquery modifier limitation reported in querydsl/querydsl#3224

Problem Statement

Previously, when users applied .limit() or .offset() to subqueries, modifiers were silently ignored during query serialization. This was particularly frustrating for Hibernate users since Hibernate 6.0+ natively supports LIMIT/OFFSET in subqueries, but QueryDSL wasn't utilizing this capability.

Example of previous behavior:

// This would ignore the .limit(1) in the subquery
query.select(cat)
    .from(cat)
    .where(cat.id.in(
        JPAExpressions.select(mate.id)
            .from(mate)
            .where(mate.weight.gt(5))
            .limit(1)  // ← This was ignored!
    ))
    .fetch();

Solution

This implementation introduces a template-based approach that allows JPA provider-specific handling of subquery modifiers:

🔧 Core Changes

  1. Template Support Detection
  • Added isSubQueryModifiersSupported() method to JPQLTemplates
  • Returns false by default (standard JPQL compliance)
  • Overridden in HQLTemplates to return true (Hibernate-specific support)
  1. Conditional Serialization
  • Enhanced JPQLSerializer.visit(SubQueryExpression) to conditionally serialize modifiers
  • Only applies LIMIT/OFFSET when the template supports it
  • Preserves existing behavior for all other JPA providers
  1. Serialization Constants
  • Added LIMIT and OFFSET constants for consistent formatting
  • Follows existing QueryDSL serialization patterns

📋 Supported Scenarios

  • ✅ Subqueries in WHERE clauses with LIMIT/OFFSET
  • ✅ Scalar subqueries in SELECT clauses with modifiers
  • ✅ Nested subqueries with independent modifiers
  • ✅ Combined LIMIT and OFFSET usage

Compatibility

✅ Backward Compatibility

  • Zero breaking changes to existing APIs
  • All existing queries continue to work exactly as before
  • No impact on users not using subquery modifiers

🎯 Provider Support

  • Hibernate: ✅ Full subquery modifier support (new feature)
  • EclipseLink: ⭕ No change (maintains current behavior)
  • OpenJPA: ⭕ No change (maintains current behavior)
  • DataNucleus: ⭕ No change (maintains current behavior)
  • BatooJPA: ⭕ No change (maintains current behavior)

Technical Implementation Details

The implementation uses a template-based approach to maintain provider neutrality:

  1. JPQLTemplates.isSubQueryModifiersSupported(): Base method returns false (JPQL standard)
  2. HQLTemplates.isSubQueryModifiersSupported(): Override returns true (Hibernate extension)
  3. JPQLSerializer: Conditionally serializes modifiers based on template support

This design ensures that:

  • Standard JPQL compliance is maintained for most providers
  • Hibernate-specific features are enabled only when appropriate
  • Future providers can easily add support by overriding the template method

This change enables the use of LIMIT and OFFSET modifiers within subqueries when using Hibernate as the JPA provider.
This addressing the limitation where modifiers were previously ignored in subquery contexts.

**Key changes:**

* Add `isSubQueryModifiersSupported()` method to JPQLTemplates
- Returns false by default (standard JPQL behavior)
- Overridden in HQLTemplates to return true (Hibernate-specific)

* Update JPQLSerializer to conditionally serialize subquery modifiers
- Add LIMIT and OFFSET constants for serialization
- Modify `visit(SubQueryExpression)` to handle modifiers based on template support
- Preserve existing behavior for non-supporting providers

* Comprehensive test coverage
- Unit tests for template support methods across all JPA providers
- Serializer tests for both JPQL and HQL templates
- Tests for various subquery contexts (WHERE, SELECT, nested subqueries)
- Edge cases with combined LIMIT and OFFSET usage

**Compatibility:**
- Maintains backward compatibility for all existing JPA providers
- Only affects Hibernate users who explicitly use subquery modifiers
- No breaking changes to existing APIs

Fixes subquery modifier limitations in Hibernate environments while preserving standard JPQL compliance for other providers.
Copy link

codecov bot commented Aug 1, 2025

Codecov Report

❌ Patch coverage is 0% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (9b9e4fc) to head (95dd7be).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...src/main/java/com/querydsl/jpa/JPQLSerializer.java 0.00% 10 Missing ⚠️
...a/src/main/java/com/querydsl/jpa/HQLTemplates.java 0.00% 1 Missing ⚠️
.../src/main/java/com/querydsl/jpa/JPQLTemplates.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master   #1304    +/-   ##
=======================================
  Coverage    0.00%   0.00%            
=======================================
  Files         812     837    +25     
  Lines       31138   31479   +341     
  Branches     3531    3544    +13     
=======================================
- Misses      31138   31479   +341     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@velo velo left a comment

Choose a reason for hiding this comment

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

Looking good, but can you please add a test to the HibernateBase, to test it for reals too.

DongGunYoon and others added 3 commits August 14, 2025 09:16
- Test subquery with LIMIT and OFFSET in WHERE clause
- Test subquery with LIMIT in SELECT clause
- Test subquery with OFFSET only
- Verify actual functionality
- Validate correct result count and data ordering
@DongGunYoon
Copy link
Contributor Author

Looking good, but can you please add a test to the HibernateBase, to test it for reals too.

Thanks for the feedback! I've added comprehensive integration tests to HibernateBase that verify the actual functionality of subquery modifiers with Hibernate execution.

@velo velo merged commit bec05ee into OpenFeign:master Aug 14, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants