1. Overview
1.概述
In this short tutorial, we’ll see how to return multiple different entities in JPA Query.
在这个简短的教程中,我们将看到如何在JPA查询中返回多个不同的实体。
First, we’ll create a simple code example containing a few different entities. Then, we’ll explain how to create a JPA Query that returns multiple different entities. Finally, we’ll show a working example in Hibernate’s JPA implementation.
首先,我们将创建一个包含几个不同实体的简单代码示例。然后,我们将解释如何创建一个JPA查询,返回多个不同的实体。最后,我们将在Hibernate的JPA实现中展示一个工作实例。
2. Example Configuration
2.配置示例
Before we explain how to return multiple entities in a single Query, let’s build an example that we’ll work on.
在我们解释如何在一个查询中返回多个实体之前,让我们建立一个例子,我们将对此进行研究。
We’ll create an app that allows its users to buy subscriptions for specific TV channels. It consists of 3 tables: Channel, Subscription, and User.
我们将创建一个应用程序,允许其用户购买特定电视频道的订阅。它由3个表组成。Channel, Subscription, 和User。
First, let’s look at the Channel entity:
首先,让我们看一下Channel实体。
@Entity
public class Channel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private Long subscriptionId;
// getters, setters, etc.
}
It consists of 3 fields that are mapped to corresponding columns. The first and the most important one is the id, which is also the primary key. In the code field, we’ll store Channel‘s code.
它由3个字段组成,被映射到相应的列。第一个也是最重要的一个是id,,它也是主键。在code字段,我们将存储Channel的代码。
Last but not least, there is also a subscriptionId column. It’ll be used to create a relation between a channel and a subscription it belongs to. One channel can belong to different subscriptions.
最后但同样重要的是,还有一个subscriptionId列。它将被用来在一个频道和它所属的订阅之间建立一种关系。一个频道可以属于不同的订阅。
Now, let’s see the Subscription entity:
现在,让我们看看Subscription实体。
@Entity
public class Subscription {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
// getters, setters, etc.
}
It’s even simpler than the first one. It consists of the id field, which is the primary key, and the subscription’s code field.
它比第一个更简单。它由id字段和订阅的code字段组成,后者是主键。
Let’s also look at the User entity:
我们也来看看User实体。
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String email;
private Long subscriptionId;
// getters, setters, etc.
}
Besides the primary key id field, it consists of email and subscriptionId fields. The latter is used to create a relation between a user and a subscription that they have chosen.
除了主键id字段,它还包括email和subscriptionId字段。后者用于在用户和他们选择的订阅之间建立关系。
3. Returning Multiple Entities in Query
3.在查询中返回多个实体
3.1. Creating the Query
3.1.创建查询
In order to create a query returning multiple different entities, we need to do 2 things.
为了创建一个返回多个不同实体的查询,我们需要做两件事。
Firstly, we need to list entities that we want to return in the SELECT part of the SQL Query, separated by a comma.
首先,我们需要在SQL查询的SELECT部分列出我们想要返回的实体,用逗号分开。
Secondly, we need to connect them with each other by their primary and corresponding foreign keys.
其次,我们需要通过它们的主键和相应的外键将它们相互连接起来。
Let’s look at our example. Imagine that we want to fetch all Channels assigned to Subscriptions that were bought by the user with the given email. The JPA Query does look like this:
让我们看一下我们的例子。想象一下,我们想获取所有分配给Subscriptions的Channels,这些都是用户用给定的email购买的。 JPA查询看起来是这样的。
SELECT c, s, u
FROM Channel c, Subscription s, User u
WHERE c.subscriptionId = s.id AND s.id = u.subscriptionId AND u.email=:email
3.2. Extracting Results
3.2.提取结果
A JPA Query that selects multiple different entities returns them in an array of Objects. What’s worth pointing out is that the array keeps the order of entities. It’s crucial information because we need to manually cast returned Objects to specific entity classes.
一个选择多个不同实体的JPA查询会以一个Objects数组的形式返回。值得注意的是,该数组保持了实体的顺序。这是很关键的信息,因为我们需要手动将返回的Objects转换为特定的实体类。
Let’s see that in action. We created a dedicated repository class that creates a query and fetches results:
让我们来看看这个动作。我们创建了一个专门的资源库类,创建一个查询并获取结果。
public class ReportRepository {
private final EntityManagerFactory emf;
public ReportRepository() {
// create an instance of entity manager factory
}
public List<Object[]> find(String email) {
EntityManager entityManager = emf.createEntityManager();
Query query = entityManager
.createQuery("SELECT c, s, u FROM Channel c, Subscription s, User u"
+ " WHERE c.subscriptionId = s.id AND s.id = u.subscriptionId AND u.email=:email");
query.setParameter("email", eamil);
return query.getResultList();
}
}
We’re using an exact query from the previous section. Then, we set an email parameter to narrow down the results. Finally, we fetch the result list.
我们使用的是上一节的精确查询。然后,我们设置一个电子邮件参数来缩小结果范围。最后,我们获取结果列表。
Let’s see how we can extract individual entities from the fetched list:
让我们看看我们如何从获取的列表中提取单个实体。
List<Object[]> reportDetails = reportRepository.find("user1@gmail.com");
for (Object[] reportDetail : reportDetails) {
Channel channel = (Channel) reportDetail[0];
Subscription subscription = (Subscription) reportDetail[1];
User user = (User) reportDetail[2];
// do something with entities
}
We iterate over the fetched list and extract entities from the given object array. Having in mind our JPA Query and the order of entities in its SELECT section, we get a Channel entity as a first element, a Subscription entity as a second, and a User entity as the last element of the array.
我们对获取的列表进行迭代,并从给定的对象数组中提取实体。考虑到我们的JPA查询和实体在其SELECT部分的顺序,我们得到一个Channel实体作为第一个元素,一个Subscription实体作为第二个元素,而一个User实体作为数组的最后一个元素。
4. Conclusion
4.总结
In this article, w discussed how to return multiple entities in the JPA query. Firstly, we created an example that we worked on later in the article. Then, we explained how to write a JPA query to return multiple different entities. Finally, we showed how to extract them from the result list.
在这篇文章中,我们讨论了如何在JPA查询中返回多个实体。首先,我们创建了一个例子,我们在文章的后面进行了研究。然后,我们解释了如何写一个JPA查询来返回多个不同的实体。最后,我们展示了如何从结果列表中提取它们。
As always, the full source code of the article is available over on GitHub.
一如既往,该文章的完整源代码可在GitHub上获得。