Отображение запроса Hibernate на пользовательский класс

1. Обзор

Когда мы используем Hibernate для извлечения данных из базы данных, по умолчанию он использует извлеченные данные для построения целого графа объекта для запрошенного объекта. Но иногда нам может потребоваться извлечь только часть данных, предпочтительно в виде плоской структуры.

В этом кратком руководстве мы увидим, как мы можем достичь этого в Hibernate, используя собственный класс.

2. Сущности

Во-первых, давайте посмотрим на объекты, которые мы будем использовать для извлечения данных:

@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
}

Здесь у нас есть две сущности - DeptEmployee и Department . Для простоты предположим, что DeptEmployee может принадлежать только одному Department.

Но у Department может быть несколько DeptEmployees .

3. Пользовательский класс результата запроса

Допустим, мы хотим напечатать список всех сотрудников с указанием только их имени и названия их отдела.

Как правило, мы получаем эти данные с помощью запроса, подобного следующему:

Query<DeptEmployee> query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee");
List<DeptEmployee> deptEmployees = query.list();

При этом будут извлечены все сотрудники, все их свойства, связанный отдел и все его свойства.

Но, в данном конкретном случае, это может быть немного дороже, поскольку нам нужно только имя сотрудника и название отдела.

Один из способов получить только необходимую нам информацию - указать свойства в предложении select.

Но когда мы делаем это, Hibernate возвращает список массивов вместо списка Objects:

Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m");
List managers = query.list();
Object[]manager = (Object[]) managers.get(0);
assertEquals("John Smith", manager[0]);
assertEquals("Sales", manager[1]);

Как мы видим, возвращаемые данные немного громоздки для обработки. Но, к счастью, мы можем заставить Hibernate заполнить эти данные в классе.

Давайте посмотрим на класс Result , который мы будем использовать для заполнения полученных данных:

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
}

Обратите внимание, что класс - это не сущность, а просто POJO. Однако мы также можем использовать объект, если у него есть конструктор, который принимает все атрибуты, которые мы хотим заполнить в качестве параметров.

Мы увидим, почему конструктор важен в следующем разделе.

4. Использование конструктора в HQL

Теперь давайте посмотрим на HQL, который использует этот класс:

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();
Result result = results.get(0);
assertEquals("John Smith", result.getEmployeeName());
assertEquals("Sales", result.getDepartmentName());

Здесь мы используем конструктор, который мы определили в _Result class, вместе со свойствами, которые мы хотим получить. Это вернет список объектов Result_ с данными, заполненными из столбцов.

Как мы видим, возвращаемый список легче обрабатывать, чем использовать список массивов объектов.

  • Важно отметить, что мы должны использовать полное имя класса в запросе. **

5. Использование ResultTransformer

Альтернативой использованию конструктора в запросе HQL является использование ResultTransformer:

Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName"
  + " from com.baeldung.hibernate.entities.DeptEmployee m");
query.setResultTransformer(Transformers.aliasToBean(Result.class));
List<Result> results = query.list();
Result result = results.get(0);
assertEquals("John Smith", result.getEmployeeName());
assertEquals("Sales", result.getDepartmentName());

Мы используем метод _Transformers.aliasToBean () , чтобы использовать полученные данные для заполнения объектов Result _ .

Следовательно, мы должны убедиться, что имена столбцов или их псевдонимы в операторе select соответствуют свойствам __Result __class.

Обратите внимание, что https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/Query.html#setResultTransformer-org.hibernate.transform.ResultTransformer- [ _Query.setResultTransformer ResultTransformer Перевозчик___ ) был начиная с Hibernate 5.2.

6. Заключение

В этой статье мы увидели, как пользовательский класс можно использовать для извлечения данных в форме, которая легко читается.

Исходный код, сопровождающий эту статью, доступен на GitHub over .