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 
}

ここでは、DeptEmployeeDepartmentの2つのエンティティがあります。 簡単にするために、 DeptEmployee 1つだけに属することができますデパートメント。

ただし、Departmentには複数のDeptEmployeesを含めることができます。

3. カスタムクエリ結果クラス

すべての従業員のリストを、自分の名前と部門の名前だけで印刷したいとします。

通常、次のようなクエリを使用してこのデータを取得します。

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

これにより、すべての従業員、すべてのプロパティ、関連する部門、およびそのすべてのプロパティが取得されます。

ただし、この特定のケースでは、従業員の名前と部門の名前だけが必要なため、これは少し高価になる可能性があります。

必要な情報のみを取得する1つの方法は、select句でプロパティを指定することです。

ただし、これを行うと、Hibernateはオブジェクトのリストではなく配列のリストを返します:

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 クラスで定義したコンストラクターと、取得するプロパティを使用します。 これにより、 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クラスのプロパティと一致することを確認する必要があります。

Query.setResultTransformer(ResultTransformer は、Hibernate5.2以降非推奨になっていることに注意してください。

6. 結論

この記事では、カスタムクラスを使用して、読みやすい形式でデータを取得する方法について説明しました。

この記事に付属するソースコードは、GitHubから入手できます。