JPA:返回多个实体的查询

Posted

技术标签:

【中文标题】JPA:返回多个实体的查询【英文标题】:JPA: Query that returns multiple entities 【发布时间】:2011-10-16 05:04:39 【问题描述】:

我正在编写一个连接三个表的 JPQL 查询。在我的结果列表中,我想获得每个匹配行的所有三个实体(希望这是有道理的)。

有什么想法吗?

Hibernate 3.x 是我的 JPA 提供程序。

【问题讨论】:

【参考方案1】:

在多对一或一对多关系的情况下,如何获取其中一个实体的多条记录?假设 A 是一个实体,B 是另一个实体,但它们有一对多的关系,当你得到结果时,你期望 B 有一条记录而 A 有超过 1 条记录?我的查询如下,但我不知道如何获取第二个实体的多条记录?

@Query("SELECT wl, gr FROM WatchList as wl, GeozoneReference gr " +
            "WHERE wl.watchlistId = gr.objWatchList.watchlistId " +
            "AND wl.watchlistId =:watchlistId")
    List<Object[]> findWatchlistByWatchlistId(@Param("watchlistId") Long watchlistId);

【讨论】:

【参考方案2】:

这是一个 Spring Data 示例,但它在 JPA 中的工作方式相同

//HQL query
 @Query("SELECT c,l,p,u FROM  Course c, Lesson l, Progress p, User u "
            + "WHERE c.id=l.courseId AND l.id = p.lessonId AND p.userId = u.id AND u.id=:userId AND c.id=:courseId")
    public List<Object[]> getLessonsWithProgress(@Param("userId") Integer userId, @Param("courseId")Integer courseId);

然后,我调用这个方法并打印结果:

List<Object[]> lst = courseRepository.getLessonsWithProgress(userId, courseId);
for (Object o[] : lst) 
    Course c = (Course) o[0];
    Lesson l = (Lesson) o[1];
    Progress p = (Progress) o[2];
    User u = (User) o[3];
    //all the classes: Course, Lesson, Progress and User have the toString() overridden with the database ID;    
    System.out.printf("\nUser: %s \n Lesson: %s \n Progress: %s \n Course: %s",u,l,p,c);

@Test 的输出在这里:

User: com.cassio.dao.model.User[ id=1965 ] 
Lesson: com.cassio.dao.model.Lesson[ id=109 ] 
Progress: com.cassio.dao.model.Progress[ id=10652 ] 
Course: com.cassio.dao.model.Course[ id=30 ]

干杯

【讨论】:

嗨,Cassion,但如果我只想要课程名称、课程 ID、进度 ID 和用户名……那该怎么办?如何处理列表数据。因为当时这一行不能被任何类区分 嗨 Utkal,考虑到我的示例代码,课程、课程、进度和用户是对象。您可以在每个类的 toString() 方法中通过 @Override 获取所需的字符串或整数。同时,这种情况的最佳实践是更改 HQL 查询,而不是获取课程 c,您可以这样做 SELECT c.name、l.id、progress.id 和 u.firstname FROM ...将得到字符串和整数而不是复杂对象。 @user1735921 我不认为 CriteriaQuery 将能够返回一个 Object[] 数组,您是否可以尝试使其适应泛型类型 或使用 DTO 对象来实现它。 @Cassioseffrin 我意识到这是不可能的,所以必须制作一个自定义投影类(或者如果我们不想使用一个类,它也可以返回一个 List 类型string 是 column 的别名,object 是可以转换为实际模型字段类型的值。 @user1735921,您做出了正确的选择。如果您使用的是 spring 数据,那么预测是最好的选择,我的意思是 DTO(数据传输对象)。看看会话 4:baeldung.com/spring-data-rest-projections-excerpts【参考方案3】:

既然你在问JPA: Query that returns multiple entities,EclipseLink 也属于它。我在这个问题上搜索了 EclipseLink。所以这是我的解决方案。希望它对你有用。

TypedQuery<Object[]> query = entityManager.createQuery("select p from Post p where   p.publisher.pubId= :ID order by p.createdAt desc",
                Object[].class);
query.setParameter("ID", publisherID);

然后您可以循环遍历结果对象并相应地转换它们。

for (Object result : query.getResultList()) 
            myList.add((Post) result);
        

你也可以试试这个,

Query query = entityManager.createQuery("select p from Post p where   p.publisher.pubId= :ID order by p.createdAt desc");

参考:http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL

【讨论】:

如果我需要从出版商和书籍这两个实体获取数据怎么办?【参考方案4】:

IIRC,您可以执行 SELECT o1, o2, o3 FROM EntityA o1, EntityB o2, EntityC o3 WHERE ....,结果将是 List&lt;Object[3]&gt;,其中数组内容将包含 o1,o2,o3 值。

【讨论】:

@John:此外,您可以从 hql 调用构造函数,因此您也可以执行 select new Foo(o1, o2, o3)... 并获取 List 而不是 List 好的,但是如果我想使用 JPA TypedQuery 怎么办:myEntityManager.createQuery("select o1, o2 ...", ) 如果您想使用实际适用于两个列表连接的 setFirstResult 怎么办?即我希望能够返回一个分页列表,它是被查询的两个实体的结果的串联。 @Thomas 什么,比如SQL UNION? @Tassos,是的,但是实体会有不同数量的字段等......我想得越多,开箱即用似乎就越困难。我想我在这里梦想着 JPA 魔法......

以上是关于JPA:返回多个实体的查询的主要内容,如果未能解决你的问题,请参考以下文章

Datanucleus JPA 命名查询返回已删除的实体

JPA 选择查询以返回带有 @ManyToOne 映射的实体

JPA - 多对多集合的分页查询返回错误数量的实体

JPA 查询未在列表中返回更新的结果

如何在唯一的映射或非对象 JPA 中返回多个结果

Spring Data JPA:查询如何返回非实体对象或对象列表?