By default Querydsl initializes only direct reference properties. In cases where longer initialization paths are required, these have to be annotated in the domain types via com.mysema.query.annotations.QueryInit annotations. QueryInit is used on properties where deep initializations are needed. The following example demonstrates the usage.
@Entity class Event { @QueryInit("customer") Account account; } @Entity class Account{ Customer customer; } @Entity class Customer{ String name; // ... }
This example 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 to be applied to all top level instances of a Query type and to enable the usage of final entity fields.
Automatic path initialization is the preferred initialization strategy, but manual initialization can be activated via the Config annotation, which is described below.
The serialization of Querydsl can be customized via Config annotations on packages and types. They customize the serialization of the annotated package or type.
The serialization options are entityAccessors to generate accessor methods for entity paths instead of public final fields (default : false), listAccessors to generate listProperty(int index) style methods (default : false), mapAccessors to generate mapProperty(Key key) style accessor methods (default : false) and createDefaultVariable to generate the default variable (default : true).
Below are some examples.
Customization of Entity type serialization :
@Config(entityAccessors=true) @Entity public class User { //... }
Customization of package content :
@Config(listAccessors=true) package com.mysema.query.domain.rel; import com.mysema.query.annotations.Config;
If you want to customize the serializer configuration globally, you can do this via the APT options querydsl.entityAccessors to enable reference field accessors, querydsl.listAccessors to enable accessors for direct indexed list access, querydsl.mapAccessors to enable accessors for direct key based map access, querydsl.prefix to override the prefix for query types(default: Q), querydsl.suffix to set a suffix for query types, querydsl.packageSuffix to set a suffix for query type packages, querydsl.createDefaultVariable to set whether default variables are created.
Using the Maven APT plugin this works for example like this :
<project> <build> <plugins> ... <plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0.2</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor> <options> <querydsl.entityAccessors>true</querydsl.entityAccessors> </options> </configuration> </execution> </executions> </plugin> ... </plugins> </build> </project>
Custom type mappings can be used on properties to override the derived Path type. This can be useful for example 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.
The following example demonstrates the usage :
@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 the Querydsl query type generation. This case is different from @Transient or @QueryTransient annotated properties, where properties are not persisted. PropertyType.NONE just omits the property from the Querydsl query type.
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.
Here is a simple example from a unit test:
@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); }
And the generated methods in the QUser query type :
public BooleanPath isManagedBy(QUser other) { return com.mysema.query.domain.DelegateTest.isManagedBy(this, other); }
Delegate methods can also be used to extend built-in types. Here are some examples
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 builtin types then subclasses with the proper delegate method usages are created :
public class QDate extends DatePath<java.sql.Date> { public QDate(BeanPath<? extends java.sql.Date> entity) { super(entity.getType(), entity.getMetadata()); } public QDate(PathMetadata<?> metadata) { super(java.sql.Date.class, metadata); } public BooleanExpression inPeriod(com.mysema.commons.lang.Pair<java.sql.Date, java.sql.Date> period) { return QueryExtensions.inPeriod(this, period); } } public class QTimestamp extends DateTimePath<java.sql.Timestamp> { public QTimestamp(BeanPath<? extends java.sql.Timestamp> entity) { super(entity.getType(), entity.getMetadata()); } public QTimestamp(PathMetadata<?> metadata) { super(java.sql.Timestamp.class, metadata); } public BooleanExpression inDatePeriod(com.mysema.commons.lang.Pair<java.sql.Date, java.sql.Date> period) { return QueryExtensions.inDatePeriod(this, period); } }
It is possible to create Querydsl query types for non annotated types by creating @QueryEntities annotations. Just place a QueryEntities annotation into a package of your choice and the classes to mirrored in the value attribute.
To actually create the types use the com.mysema.query.apt.QuerydslAnnotationProcessor. In Maven you do it like this :
<project> <build> <plugins> ... <plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0.2</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.mysema.query.apt.QuerydslAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> ... </plugins> </build> </project>