Querydsl provides two ways to customize results, FactoryExpressions for row based transformation and ResultTransformer for aggregation.
The com.mysema.query.types.FactoryExpression interface is used for Bean creation,
  constructor invocation and for the creation of more complex objects. The functionality of the 
  FactoryExpression implementations of Querydsl can be accessed via the 
  com.mysema.query.types.Projections class.
For the com.mysema.query.ResultTransformer interface GroupBy is the
  main implementation.
Since Querydsl 3.0 the default type for multi-column results is com.mysema.query.Tuple.
    Tuple provides provides a typesafe Map like interface to access column data from a Tuple row object.
List<Tuple> result = query.from(employee).list(employee.firstName, employee.lastName); for (Tuple row : result) { System.out.println("firstName " + row.get(employee.firstName)); System.out.println("lastName " + row.get(employee.lastName)); }}
This example could also have been written via the QTuple expression class like this
List<Tuple> result = query.from(employee).list(new QTuple(employee.firstName, employee.lastName)); for (Tuple row : result) { System.out.println("firstName " + row.get(employee.firstName)); System.out.println("lastName " + row.get(employee.lastName)); }}
In cases where Beans need to be populated based on the results of the query, Bean projections can be used like this
List<UserDTO> dtos = query.list(
    Projections.bean(UserDTO.class, user.firstName, user.lastName));
When fields should be directly used instead of setters the following variant can be used instead
List<UserDTO> dtos = query.list(
    Projections.fields(UserDTO.class, user.firstName, user.lastName));
Constructor based row transformation can be used like this
List<UserDTO> dtos = query.list(
    Projections.bean(UserDTO.class, user.firstName, user.lastName));
As an alternative to the generic Constructor expression usage constructors
    can also be annotated with the QueryProjection annotation:
    
class CustomerDTO { @QueryProjection public CustomerDTO(long id, String name){ ... } }
And then you can use it like this in the query
QCustomer customer = QCustomer.customer; JPQLQuery query = new HibernateQuery(session); List<CustomerDTO> dtos = query.from(customer).list(new QCustomerDTO(customer.id, customer.name));
While the example is Hibernate specific, this feature is available in all modules.
If the type with the QueryProjection annotation is not an annotated entity type, you can use the constructor projection like in the example, but if the annotated type would be an entity type, then the constructor projection would need to be created via a call to the static create method of the query type:
@Entity class Customer { @QueryProjection public Customer(long id, String name){ ... } }
QCustomer customer = QCustomer.customer;
JPQLQuery query = new HibernateQuery(session);
List<Customer> dtos = query.from(customer).list(QCustomer.create(customer.id, customer.name));   
Alternatively, if code generation is not an option, you can create a constructor projection like this:
List<Customer> dtos = query.from(customer)
    .list(ConstructorExpression.create(Customer.class, customer.id, customer.name));   
      The
      com.mysema.query.group.GroupBy
      class provides aggregation functionality which can be used to aggregate query results
      in memory. Below are some usage examples.
    
Aggregating parent child relations
import static com.mysema.query.group.GroupBy.*; Map<Integer, List<Comment>> results = query.from(post, comment) .where(comment.post.id.eq(post.id)) .transform(groupBy(post.id).as(list(comment)));
This will return a map of post ids to related comments.
Multiple result columns
    
Map<Integer, Group> results = query.from(post, comment)
    .where(comment.post.id.eq(post.id))
    .transform(groupBy(post.id).as(post.name, set(comment.id)));
This will return a map of post ids to Group instances with access to post name and comment ids.
Group is the GroupBy equivalent to the Tuple interface.
More examples can be found here .