Code Generation
Querydsl uses Java annotation processing (APT) for code generation in the JPA and MongoDB modules. This section describes various configuration options for the code generation and alternatives to APT usage.
Path Initialization
By default, Querydsl initializes only reference properties of the first two
levels. When longer initialization paths are required, annotate the domain
types with com.querydsl.core.annotations.QueryInit:
@Entity
class Event {
@QueryInit("customer.address")
Account account;
}
@Entity
class Account {
Customer customer;
}
@Entity
class Customer {
String name;
Address address;
// ...
}
This enforces the initialization of the account.customer path when an
Event path is initialized as a root path / variable. The path initialization
format supports wildcards as well, e.g. "customer.*" or just "*".
The automatic path initialization replaces the manual one, which required the entity fields to be non-final. The declarative format has the benefit of being applied to all top-level instances of a query type and enabling the usage of final entity fields.
Automatic path initialization is the preferred initialization strategy, but
manual initialization can be activated via the @Config annotation.
Customization
The serialization of Querydsl can be customized via @Config annotations on
packages and types.
Config Options
| Name | Description |
|---|---|
entityAccessors |
Accessor methods for entity paths instead of public final fields (default: false) |
listAccessors |
listProperty(int index) style methods (default: false) |
mapAccessors |
mapProperty(Key key) style accessor methods (default: false) |
createDefaultVariable |
Generate the default variable (default: true) |
defaultVariableName |
Name of the default variable |
Examples:
Customization of entity type serialization:
@Config(entityAccessors=true)
@Entity
public class User {
//...
}
Customization of package content:
@Config(listAccessors=true)
package com.querydsl.core.domain.rel;
import com.querydsl.core.annotations.Config;
APT Options
To customize the serializer configuration globally, use the following APT options:
| Name | Description |
|---|---|
querydsl.entityAccessors |
Enable reference field accessors |
querydsl.listAccessors |
Enable accessors for direct indexed list access |
querydsl.mapAccessors |
Enable accessors for direct key-based map access |
querydsl.prefix |
Override the prefix for query types (default: Q) |
querydsl.suffix |
Set a suffix for query types |
querydsl.packageSuffix |
Set a suffix for query type packages |
querydsl.createDefaultVariable |
Set whether default variables are created |
querydsl.unknownAsEmbeddable |
Set whether unknown non-annotated classes should be treated as embeddable (default: false) |
querydsl.includedPackages |
Comma-separated list of packages to include into code generation (default: all) |
querydsl.includedClasses |
Comma-separated list of class names to include into code generation (default: all) |
querydsl.excludedPackages |
Comma-separated list of packages to exclude from code generation (default: none) |
querydsl.excludedClasses |
Comma-separated list of class names to exclude from code generation (default: none) |
querydsl.useFields |
Set whether fields are used as metadata source (default: true) |
querydsl.useGetters |
Set whether accessors are used as metadata source (default: true) |
querydsl.generatedAnnotationClass |
Fully qualified class name of the annotation to add on generated sources |
Using maven-compiler-plugin
The recommended approach is to configure maven-compiler-plugin to hook APT
directly into compilation:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<generatedSourcesDirectory>target/generated-sources/java</generatedSourcesDirectory>
<compilerArgs>
<arg>-Aquerydsl.entityAccessors=true</arg>
<arg>-Aquerydsl.useFields=false</arg>
</compilerArgs>
</configuration>
<dependencies>
<dependency>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>7.1</version>
<classifier>jpa</classifier>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</plugin>
You need to use a proper classifier when defining the dependency on
io.github.openfeign.querydsl:querydsl-apt. The additional artifacts define the
annotation processor to be used in
META-INF/services/javax.annotation.processing.Processor.
Available classifiers:
generalhibernatejpa
With this configuration, query objects have their sources generated and compiled during compilation of the domain objects. This also automatically adds the generated sources directory to Maven project source roots.
Custom Type Mappings
Custom type mappings can be used on properties to override the derived Path
type. This is useful in cases where comparison and String operations should be
blocked on certain String paths, or Date/Time support for custom types needs
to be added.
Support for Date/Time types of the Joda time API and JDK (java.util.Date,
Calendar and subtypes) is built in, but other APIs might need to be
supported using this feature.
@Entity
public class MyEntity {
@QueryType(PropertyType.SIMPLE)
public String stringAsSimple;
@QueryType(PropertyType.COMPARABLE)
public String stringAsComparable;
@QueryType(PropertyType.NONE)
public String stringNotInQuerydsl;
}
The value PropertyType.NONE can be used to skip a property in query type
generation. This is different from @Transient or @QueryTransient
annotated properties, where properties are not persisted. PropertyType.NONE
just omits the property from the Querydsl query type.
Delegate Methods
To declare a static method as a delegate method, add the @QueryDelegate
annotation with the corresponding domain type as a value and provide a method
signature that takes the corresponding Querydsl query type as the first
argument.
@QueryEntity
public static class User {
String name;
User manager;
}
@QueryDelegate(User.class)
public static BooleanPath isManagedBy(QUser user, User other) {
return user.manager.eq(other);
}
The generated method in the QUser query type:
public BooleanPath isManagedBy(QUser other) {
return DelegateTest.isManagedBy(this, other);
}
Delegate methods can also extend built-in types:
public class QueryExtensions {
@QueryDelegate(Date.class)
public static BooleanExpression inPeriod(DatePath<Date> date, Pair<Date,Date> period) {
return date.goe(period.getFirst()).and(date.loe(period.getSecond()));
}
@QueryDelegate(Timestamp.class)
public static BooleanExpression inDatePeriod(DateTimePath<Timestamp> timestamp, Pair<Date,Date> period) {
Timestamp first = new Timestamp(DateUtils.truncate(period.getFirst(), Calendar.DAY_OF_MONTH).getTime());
Calendar second = Calendar.getInstance();
second.setTime(DateUtils.truncate(period.getSecond(), Calendar.DAY_OF_MONTH));
second.add(1, Calendar.DAY_OF_MONTH);
return timestamp.goe(first).and(timestamp.lt(new Timestamp(second.getTimeInMillis())));
}
}
When delegate methods are declared for built-in types, subclasses with the proper delegate method usages are created.
Non-annotated Types
It is possible to create Querydsl query types for non-annotated types by
creating @QueryEntities annotations. Place a @QueryEntities annotation
into a package of your choice and the classes to mirror in the value attribute.
To create the types, use the com.querydsl.apt.QuerydslAnnotationProcessor.
In Maven, configure the maven-compiler-plugin:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<generatedSourcesDirectory>target/generated-sources/java</generatedSourcesDirectory>
</configuration>
<dependencies>
<dependency>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>7.1</version>
<classifier>general</classifier>
</dependency>
</dependencies>
</plugin>
Classpath-based Code Generation
For cases where annotated Java sources are not available, such as the usage of
a different JVM language (Scala, Groovy) or annotation addition via bytecode
manipulation, the GenericExporter class can be used to scan the classpath
for annotated classes and generate query types.
Add a dependency to the querydsl-codegen module:
<dependency>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-codegen</artifactId>
<version>7.1</version>
</dependency>
Example for JPA:
GenericExporter exporter = new GenericExporter();
exporter.setKeywords(Keywords.JPA);
exporter.setEntityAnnotation(Entity.class);
exporter.setEmbeddableAnnotation(Embeddable.class);
exporter.setEmbeddedAnnotation(Embedded.class);
exporter.setSupertypeAnnotation(MappedSuperclass.class);
exporter.setSkipAnnotation(Transient.class);
exporter.setTargetFolder(new File("target/generated-sources/java"));
exporter.export(DomainClass.class.getPackage());
This exports all JPA-annotated classes in the package of DomainClass and
subpackages to the target/generated-sources/java directory.
Usage via Maven
The goals generic-export, jpa-export, and jdo-export of the
querydsl-maven-plugin can be used for GenericExporter usage via Maven.
| Type | Element | Description |
|---|---|---|
File |
targetFolder |
Target folder for generated sources |
boolean |
scala |
true if Scala sources should be generated instead (default: false) |
String[] |
packages |
Packages to be introspected for entity classes |
boolean |
handleFields |
true if fields should be treated as properties (default: true) |
boolean |
handleMethods |
true if getters should be treated as properties (default: true) |
String |
sourceEncoding |
Charset encoding for generated source files |
boolean |
testClasspath |
true if the test classpath should be used instead |
Example for JPA annotated classes:
<plugin>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>7.1</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>jpa-export</goal>
</goals>
<configuration>
<targetFolder>target/generated-sources/java</targetFolder>
<packages>
<package>com.example.domain</package>
</packages>
</configuration>
</execution>
</executions>
</plugin>
This exports the JPA-annotated classes of the com.example.domain package and
subpackages to the target/generated-sources/java directory.
If you need to compile the generated sources directly after that, use the
compile goal:
<execution>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceFolder>target/generated-sources/java</sourceFolder>
</configuration>
</execution>
Scala Support
For Scala output, use a variant of the following configuration:
<plugin>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>7.1</version>
<dependencies>
<dependency>
<groupId>io.github.openfeign.querydsl</groupId>
<artifactId>querydsl-scala</artifactId>
<version>7.1</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>jpa-export</goal>
</goals>
<configuration>
<targetFolder>target/generated-sources/scala</targetFolder>
<scala>true</scala>
<packages>
<package>com.example.domain</package>
</packages>
</configuration>
</execution>
</executions>
</plugin>