Important Notice
Thank you for opening an issue! Please note that, as outlined in the README, I currently only work on feature requests or bug fixes when sponsored. Balancing this project with professional and personal priorities means I have a very limited amount of effort I can divert to this project.
You must put in the work to address this issue, or it won't be addressed.
- [V] I am willing to put in the work and submit a PR to resolve this issue.
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Motivation
QueryDSL provides a readable, type-safe query API for select, update, and delete operations in JPA projects. However, there is no way to retrieve generated keys after an insert in the JPA module. This forces developers to fall back to EntityManager.persist() + flush() just for insert + key return, breaking the consistent QueryDSL style.
The SQL module already supports executeWithKey(), but using it in a JPA project requires a separate SQLQueryFactory configuration, SQL-specific Q-classes generated from the DB schema, and managing two different query factories. This is excessive overhead just for insert key return.
Before / After
Before (current) — must break out of QueryDSL for insert + key return:
@Autowired JPAQueryFactory queryFactory;
// insert + key return → forced to use EntityManager
entityManager.persist(entity);
entityManager.flush();
Long seq = entity.getSeq();
// back to QueryDSL for update
queryFactory.update(role)
.set(role.role, "ROLE_" + seq)
.where(role.seq.eq(seq))
.execute();
After (with this feature) — everything stays in QueryDSL:
@Autowired JPAQueryFactory queryFactory;
// insert + key return
Long seq = queryFactory.insert(role)
.set(role.name, dto.roleName())
.set(role.status, status)
.set(role.description, dto.description())
.set(role.createdBy, actorSeq)
.set(role.createdAt, LocalDateTime.now())
.executeWithKey(role.seq);
// update with generated key
queryFactory.update(role)
.set(role.role, "ROLE_" + seq)
.where(role.seq.eq(seq))
.execute();
Proposed Solution
Add executeWithKey(Path) and executeWithKey(Class) to both JPAInsertClause and HibernateInsertClause.
Since JPA's Query.executeUpdate() only returns affected row count and has no API for generated keys, the implementation bypasses JPQL and executes a native SQL INSERT via JDBC with Statement.RETURN_GENERATED_KEYS:
Reads @table / @column annotations to build native SQL (same pattern as NativeSQLSerializer)
HibernateInsertClause uses Session.doReturningWork() for JDBC access
JPAInsertClause uses EntityManager.unwrap(Session.class).doReturningWork()
Limitations
INSERT ... SELECT subqueries are not supported (throws UnsupportedOperationException)
Requires explicit @table / @column annotations if using a custom Hibernate PhysicalNamingStrategy
JPAInsertClause currently relies on Hibernate as the JPA provider for JDBC connection access
Important Notice
Thank you for opening an issue! Please note that, as outlined in the README, I currently only work on feature requests or bug fixes when sponsored. Balancing this project with professional and personal priorities means I have a very limited amount of effort I can divert to this project.
You must put in the work to address this issue, or it won't be addressed.
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
Motivation
QueryDSL provides a readable, type-safe query API for select, update, and delete operations in JPA projects. However, there is no way to retrieve generated keys after an insert in the JPA module. This forces developers to fall back to EntityManager.persist() + flush() just for insert + key return, breaking the consistent QueryDSL style.
The SQL module already supports executeWithKey(), but using it in a JPA project requires a separate SQLQueryFactory configuration, SQL-specific Q-classes generated from the DB schema, and managing two different query factories. This is excessive overhead just for insert key return.
Before / After
Before (current) — must break out of QueryDSL for insert + key return:
After (with this feature) — everything stays in QueryDSL:
Proposed Solution
Add executeWithKey(Path) and executeWithKey(Class) to both JPAInsertClause and HibernateInsertClause.
Since JPA's Query.executeUpdate() only returns affected row count and has no API for generated keys, the implementation bypasses JPQL and executes a native SQL INSERT via JDBC with Statement.RETURN_GENERATED_KEYS:
Reads @table / @column annotations to build native SQL (same pattern as NativeSQLSerializer)
HibernateInsertClause uses Session.doReturningWork() for JDBC access
JPAInsertClause uses EntityManager.unwrap(Session.class).doReturningWork()
Limitations
INSERT ... SELECT subqueries are not supported (throws UnsupportedOperationException)
Requires explicit @table / @column annotations if using a custom Hibernate PhysicalNamingStrategy
JPAInsertClause currently relies on Hibernate as the JPA provider for JDBC connection access