Search code examples
javahibernatehql

Hibernate custom DTO with a list field


I have 2 entities

@Entity
public class DeptEmployee {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String employeeNumber;

    private String designation;

    private String name;

    @ManyToOne
    private Department department;

    // constructor, getters and setters 
}
@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String name;

    @OneToMany(mappedBy="department")
    private List<DeptEmployee> employees;

    public Department(String name) {
        this.name = name;
    }

    // getters and setters 
}

I know that I can extract the DTO Result like this:

public class Result {
    private String employeeName;

    private String departmentName;

    public Result(String employeeName, String departmentName) {
        this.employeeName = employeeName;
        this.departmentName = departmentName;
    }

    public Result() {
    }

    // getters and setters 
}
Query<Result> query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)"
  + " from com.baeldung.hibernate.entities.DeptEmployee m");
List<Result> results = query.list();

(thanks to the example in this article: https://www.baeldung.com/hibernate-query-to-custom-class)



Now I would like to extract a DTO which contains a department name and a list of the names of the employees in this department.

public class Result2 {
    private String departmentName;

    private List<String> employeeNames;

    // Constructor ???

    public Result2() {
    }

    // getters and setters 
}

My questions are:

  • is that possible?
  • what is the constructor in Result2?
  • what is the hql query to extract this Result2?

Solution

  • I think that you can not achieve it in HQL. You can use what you already have. Remap List<Result> to List<Result2>. Frist group by departmentName after that you can create Result2 objects. The sql query and transferred data will be rather the same.

    List<Result2> results= query.list().stream()
      .collect(groupingBy(Result::getDepartmentName))
      .entrySet().stream()
      .map(e -> new Result2(
        e.getKey(),
        e.getValue().stream().map(Result::getEmployeeName).collect(Collectors.toList())))
      .collect(Collectors.toList());