3.2. Configuration

3.2.1. Path initialization

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 usage. 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 declarative 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.

Declarative path initialization is the preferred initialization strategy, but manual initialization can be activated via the QuerydslConfig annotation, which is described below.

3.2.2. Customization of serialization

The serialization of Querydsl can be customized via QuerydslConfig 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 :

@QuerydslConfig(entityAccessors=true)
@Entity
public class User {
	//...
}  	  

Customization of package content :

@QuerydslConfig(listAccessors=true)
package com.mysema.query.domain.rel;

import com.mysema.query.annotations.QuerydslConfig;

If you want to customize the serializer configuration globally, you can do this via the APT options querydsl.entityAccessors, querydsl.listAccessors, querydsl.mapAccessors and querydsl.createDefaultVariable.

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</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>

3.2.3. Custom type mappings

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.

3.2.4. Custom methods in query types

Querydsl provides the possibility to annotate methods for mirroring in query types. Methods can either be annotated directly in the context of the class where they belong or in query extension interfaces, if the target class is only available for annotation.

Example 1 :

    
public class Point{
  // ...   
}

@QueryExtensions(Point.class)
public interface PointOperations {

   @QueryMethod("geo_distance({0}, {1})")
   int geoDistance(Point otherPoint);

}    

The first example describes indirect annotation via QueryExtensions usage. Let's assume that Point is a class of an external library which has to be used as such without the possibility of customization in source form.

To make a geoDistance(Point) method available in the Querydsl query type for Point, a query extension interface is used. Via the QueryExtensions annotation the interface is bound to the Point class and via the QueryMethod annotation the geoDistance method is declared to be mirrored into the Point query type with a serialization pattern of "geo_distance({0}, {1})".

The serialization patterns of query methods have the host object itself always as the first argument and the method parameters as further arguments.

Example 2 :

public class Point{

    @QueryMethod("geo_distance({0}, {1})")
    int geoDistance(Point otherPoint){
       // dummy implementation
        return 0;
    }
   
}

The second example features the same use case as in the first example, but this time the Point class is annotated directly. This approach is feasible, if the related domain type is available for annotation and APT post processing.

3.2.5. Delegate methods

Instead of custom methods with serialization templates, static delegates can be used.

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);
    }

}

3.2.6. Query type generation for not annotated types

It is possible to create Querydsl query types for not 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</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>