Installation
Requirements
| Dependency | Version | Note |
|---|---|---|
| Spring Boot | 3.0+ | CI tests 3.0, 3.2, 3.3, 3.4. |
| QueryDSL | 5.1.0+ | Both original (com.querydsl) and OpenFeign fork (io.github.openfeign.querydsl 6.x) are supported. CI tests both. |
| Kotlin | 1.7+ | |
| Java | 17+ |
Prerequisites
QueryDSL Q-class generation (APT or KSP) must be configured in your project. See QueryDSL documentation for setup instructions.
Add the Dependency
implementation("io.github.harryjhin:querydsl-ktx-spring-boot-starter:1.1.0")implementation 'io.github.harryjhin:querydsl-ktx-spring-boot-starter:1.1.0'<dependency>
<groupId>io.github.harryjhin</groupId>
<artifactId>querydsl-ktx-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>That's it. The starter brings in everything you need.
Module Selection Guide
The library ships three modules. Choose based on your needs:
| Module | What it provides | When to use |
|---|---|---|
querydsl-ktx-spring-boot-starter | Core + AutoConfiguration | Most projects. Adds a JPAQueryFactory bean automatically. |
querydsl-ktx | Extension interfaces + QuerydslRepository base class | You already register your own JPAQueryFactory bean and only need the Kotlin extensions. |
querydsl-ktx-spring-boot | AutoConfiguration only | You want the auto-registered JPAQueryFactory but will implement extension interfaces yourself. |
Starter (recommended)
// Pulls in both querydsl-ktx and querydsl-ktx-spring-boot
implementation("io.github.harryjhin:querydsl-ktx-spring-boot-starter:1.1.0")Core only
// Extension interfaces only, no AutoConfiguration
implementation("io.github.harryjhin:querydsl-ktx:1.1.0")When to use core only
Use querydsl-ktx alone when:
- You register
JPAQueryFactorywith customJPQLTemplates - You use a non-Spring framework
- You want zero auto-configuration magic
AutoConfiguration
The starter auto-registers a JPAQueryFactory bean with these conditions:
| Condition | Purpose |
|---|---|
@ConditionalOnClass(JPAQueryFactory) | Only activates when QueryDSL is on the classpath |
@ConditionalOnSingleCandidate(EntityManagerFactory) | Activates when exactly one EntityManagerFactory is present, or one is marked @Primary |
@ConditionalOnMissingBean | Respects any custom JPAQueryFactory you define |
@AutoConfiguration(after = HibernateJpaAutoConfiguration) | Runs after Spring Boot JPA auto-configuration completes |
Bean creation:
@Bean
@ConditionalOnMissingBean
fun jpaQueryFactory(entityManagerFactory: EntityManagerFactory): JPAQueryFactory =
JPAQueryFactory(SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory))SharedEntityManagerCreator produces a transactional EntityManager proxy managed by Spring. This is the same pattern Spring Data JPA uses internally.
Custom JPAQueryFactory
If you register your own JPAQueryFactory bean (e.g., with custom JPQLTemplates), the auto-configuration backs off automatically. No exclusions needed.
@Configuration
class QuerydslConfig {
@Bean
fun jpaQueryFactory(entityManager: EntityManager) =
JPAQueryFactory(JPQLTemplates.DEFAULT, entityManager)
}Multi-datasource Setup
With multiple EntityManagerFactory beans, the one marked @Primary is selected automatically.
@Configuration
class DataSourceConfig {
@Bean
@Primary
fun primaryEntityManagerFactory(
builder: EntityManagerFactoryBuilder,
@Qualifier("primaryDataSource") dataSource: DataSource,
): LocalContainerEntityManagerFactoryBean =
builder.dataSource(dataSource).packages("com.example.primary").build()
@Bean
fun secondaryEntityManagerFactory(
builder: EntityManagerFactoryBuilder,
@Qualifier("secondaryDataSource") dataSource: DataSource,
): LocalContainerEntityManagerFactoryBean =
builder.dataSource(dataSource).packages("com.example.secondary").build()
}With this setup, the auto-registered JPAQueryFactory uses the primary datasource.
To query the secondary datasource, register a separate JPAQueryFactory:
@Configuration
class SecondaryQuerydslConfig {
@Bean
fun secondaryJpaQueryFactory(
@Qualifier("secondaryEntityManagerFactory") emf: EntityManagerFactory,
): JPAQueryFactory =
JPAQueryFactory(SharedEntityManagerCreator.createSharedEntityManager(emf))
}No @Primary Marker
If multiple EntityManagerFactory beans exist without @Primary, the auto-configuration stays inactive. You must register JPAQueryFactory manually.
Verify the Setup
Create a simple repository to confirm everything works:
@Repository
class TestRepository : QuerydslRepository<YourEntity>() {
private val entity = QYourEntity.yourEntity
fun findAll(): List<YourEntity> =
selectFrom(entity).fetch()
}If this compiles and runs, your setup is complete. Head to Quick Start to write your first dynamic query.
GraalVM Native Image
querydsl-ktx provides RuntimeHintsRegistrar for GraalVM native image compatibility. The auto-configuration automatically registers reflection hints needed by the library.
QueryDSL Upstream Limitation
QueryDSL 5.1.0 does not officially support GraalVM native image (querydsl/querydsl#3646). You may need additional reflection configuration for QueryDSL core classes when building native images.