如何通过 Java 中的 JPA 2.1 获得包含属性和列表的多选结果?

Nab*_*abi 5 jpa projection one-to-many

目标是使用多选获取员工的名字、姓氏和待办事项列表:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root emp = q.from(Employee.class);

q.multiselect(
    emp.get("firstName").alias("fname"),
    emp.get("lastName").alias("lname"),
    emp.get("toDoList").alias("toDoList")
).where(cb.equal(emp.get("id"), 12345));

List<Tuple> tuples = em.createQuery(q).getResultList();
Iterator<Tuple> iter = tuples.iterator();

while(iter.hasNext()){
    Tuple t = iter.next();
    //t.get("fName");     // returns String
    //t.get("lName");     // returns String
    //t.get("toDoList");  // returns String

    //?????
    //...

}
Run Code Online (Sandbox Code Playgroud)

toDoList 只是一个简单的字符串列表。假设员工 12345 有 4 个待办事项。这意味着我得到以下结果集:

---------------------------------
| firstName | lastName | toDo   |
---------------------------------
| John      | Doe      | sleep  |
---------------------------------
| John      | Doe      | eat    |
---------------------------------
| John      | Doe      | play   |
---------------------------------
| John      | Doe      | laugh  |
---------------------------------
Run Code Online (Sandbox Code Playgroud)

现在我正在寻找一种聪明的方法来创建一个 ONE Employee 的实例并设置它的 firstName、lastName 和 toDoList ONCE:

Employee employee = new Employee();
employee.setFirstName(...);
employee.setLastName(...);
employee.setToDoList(...); 
Run Code Online (Sandbox Code Playgroud)

最好的方法是什么?如果我添加其他关系(即最喜爱的歌曲),事情会变得更加复杂。

Nab*_*abi 2

不幸的是,您必须为多选调用的每个组合编写代码才能从元组列表中获取数据,并且该代码可能非常脏。

通过一个查询获取关系存在主要缺点:

  • 用于读取数据的java代码会变得非常脏
  • 一个查询一开始听起来性能不错,但这将为每个获取的行检索重复的数据

所以我实际上相信在许多情况下执行单独的查询来获取数据是更好的方法(就像我的情况一样)。换句话说,我将避免混乱的代码并使用单选。用于获取投影数据的生成代码更易于维护且更具可读性。以下是我发现的一些重要链接:

具有连接获取功能的 JPQL SQL

用户可能希望加载每个关系,但是连接获取每个关系,特别是每个 ToMany 关系将导致巨大的连接(即外连接),从而获取大量重复数据。

2. JPQL中的Fetch Join

主要缺点是我们需要编写额外的代码来执行查询。但如果实体具有多个关系并且我们需要为不同的用例初始化不同的关系,情况会变得更糟。在这种情况下,我们需要为获取连接关系的每个所需组合编写一个查询。这可能会变得非常混乱。