JPA:返回多个实体的查询

52

我正在编写一条跨三个表连接的JPQL查询。在我的结果列表中,我希望每个匹配行返回三个实体(希望这样说得清楚)。

有什么想法吗?

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

4个回答

59

据我所知,您可以执行 SELECT o1, o2, o3 FROM EntityA o1, EntityB o2, EntityC o3 WHERE ....,结果将是一个 List<Object[3]>,其中数组内容将包含o1、o2、o3的值。


12
另外,你可以在HQL中调用构造函数,因此你也可以使用 select new Foo(o1, o2, o3)... 而得到一个 List<Foo> 而不是一个 List<Object[]>。 - Ryan Stewart
4
好的,如果我想使用JPA TypedQuery该怎么办:myEntityManager.createQuery("select o1, o2 ...", <这里放什么?>) - AgostinoX
如果您想使用setFirstResult,将其应用于两个列表的连接,该怎么办?也就是说,我希望能够返回一个分页列表,该列表是查询的两个实体结果的连接。 - Thomas
直到您升级到Hibernate 5.1之前,您无法在不相关的实体之间执行左外连接。https://hibernate.atlassian.net/browse/HHH-16 - kisna
如何在条件查询中执行此查询? - user1735921
显示剩余4条评论

41

这是一个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 patel
嗨Utkal,考虑到我的示例代码,Course,Lesson,Progress和User都是对象。您可以通过在每个类的toString()方法中进行@ Override来获取所需的String或Integer。同时,最好的做法是更改HQL查询,而不是获取Course c,您可以这样做SELECT c.name,l.id,progress.id和u.firstname FROM ...这样您就可以获得Strings和Integers而不是复杂对象。 - Cassio Seffrin
如何从标准查询中获取List<Object[]>类型的结果? - user1735921
1
@user1735921,我认为CriteriaQuery无法返回Object[]数组,你可以尝试将其适配为泛型类型<T>,或者使用DTO对象来实现。 - Cassio Seffrin
1
@CassioSeffrin 我意识到这是不可能的,所以不得不制作一个自定义投影类(或者如果我们不想使用类,它也可以返回List<Map<String,Object>>类型,其中字符串是列的别名,对象是值,可以强制转换为实际模型字段类型)。 - user1735921
1
@user1735921,你做出了正确的选择。如果你正在使用Spring Data,投影是最好的选择,投影就是我所说的DTO(数据传输对象)。请查看第4节:https://www.baeldung.com/spring-data-rest-projections-excerpts - Cassio Seffrin

2

如果存在一对多或多对一的关系,如何获取一个实体的多个记录?比如说A是一个实体,B是另一个实体,它们之间有一对多的关系,当你获得结果时,你希望B有一个记录,而A有多个记录。下面是我的查询语句,但我不知道该如何获取第二个实体的多个记录:

最初的回答:

如果您想获取与一个实体相关联的多个记录,可以使用JOIN语句。在您的情况下,您需要使用LEFT JOIN来检索所有A的记录,即使没有匹配的B记录。

您的查询可能如下所示:

SELECT A.*, B.*
FROM A
LEFT JOIN B ON A.id = B.a_id
WHERE A.id = [your_id]

这将返回所有与A.id匹配的B记录和所有A记录。

@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

由于您正在询问JPA:返回多个实体的查询,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");

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


如果我需要从两个实体(比如出版商和书籍)中获取数据怎么办? - fiddle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接