Search code examples
hibernatejpacriteria

Criteria query for pojo with List field


I need to query from DB POJO instead of whole entity. And it is pretty simple while POJO contains "simple" field types like String, Integer and etc. For example if EmployeeInfo class contains only name and salary we can do like that:

  CriteriaQuery<EmployeeInfo> query = cb.createQuery(EmployeeInfo.class);
  Root<Employee> employee = query.from(Employee.class);
  query.multiselect(employee.get(Employee_.name),
          employee.get(Employee_.salary));

But can I select not only plain POJO? Imagine that we need to add to EmployeeInfo new field like List tasks. Please help me find a way how to query Pojo with List field. Thanks in advence.


Solution

  • That's not directly possible. You would have to join the list and then in your code rebuild the structure by doing some grouping. Since this is a painful task that involves quite a lot of boilerplate code, I think this is a perfect use case for Blaze-Persistence Entity Views.

    I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

    A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

    @EntityView(Employee.class)
    public interface EmployeeInfo {
        @IdMapping
        Long getId();
        String getName();
        BigDecimal getSalary();
        Set<TaskInfo> getTasks();
    
        @EntityView(Task.class)
        interface TaskInfo {
            @IdMapping
            Long getId();
            String getName();
        }
    }
    

    Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

    EmployeeInfo a = entityViewManager.find(entityManager, EmployeeInfo.class, id);

    The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

    Page<EmployeeInfo> findAll(Pageable pageable);
    

    The best part is, it will only fetch the state that is actually necessary!