1. Обзор
В этом кратком руководстве мы увидим, как вернуть несколько разных сущностей в JPA Query. ``
Сначала мы создадим простой пример кода, содержащий несколько разных сущностей. Затем мы объясним, как создать запрос JPA, который возвращает несколько разных сущностей. Наконец, мы покажем рабочий пример реализации Hibernate JPA.
2. Пример конфигурации
Прежде чем мы объясним, как вернуть несколько сущностей в одном запросе, давайте создадим пример, над которым мы будем работать.
Мы создадим приложение, позволяющее пользователям покупать подписки на определенные телеканалы. Он состоит из 3 таблиц: Channel
, Subscription
и User
.
Во-первых, давайте посмотрим на сущность Channel :
@Entity
public class Channel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private Long subscriptionId;
// getters, setters, etc.
}
Он состоит из 3 полей, которые сопоставлены с соответствующими столбцами. Первым и самым важным является идентификатор,
который также является первичным ключом. В поле кода
мы будем хранить код канала
.
И последнее, но не менее важное: есть столбец « subscriptionId ».
Он будет использоваться для создания связи между каналом и подпиской, которой он принадлежит. Один канал может принадлежать разным подпискам.
Теперь давайте посмотрим на сущность Subscription :
@Entity
public class Subscription {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
// getters, setters, etc.
}
Он даже проще первого. Он состоит из поля id
, которое является первичным ключом, и поля кода подписки.
Давайте также посмотрим на сущность User :
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String email;
private Long subscriptionId;
// getters, setters, etc.
}
Помимо поля идентификатора
первичного ключа , оно состоит из полей электронной почты
и идентификатора подписки .
Последний используется для создания связи между пользователем и выбранной им подпиской.
3. Возврат нескольких объектов в запросе
3.1. Создание запроса
Чтобы создать запрос, возвращающий несколько разных сущностей, нам нужно сделать 2 вещи.
Во-первых, нам нужно перечислить объекты, которые мы хотим вернуть, в части SELECT
SQL-запроса, разделенные запятой.
Во-вторых, нам нужно связать их друг с другом по первичному и соответствующему внешнему ключу.
Давайте посмотрим на наш пример. Представьте, что мы хотим получить все каналы
, назначенные подпискам
, которые были куплены пользователем с указанным адресом электронной почты .
Запрос 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. Извлечение результатов
Запрос JPA, который выбирает несколько разных сущностей, возвращает их в массиве Objects
. Стоит отметить, что массив сохраняет порядок сущностей. Это важная информация, потому что нам нужно вручную привести возвращаемые объекты к определенным классам сущностей.
Давайте посмотрим, что в действии. Мы создали специальный класс репозитория, который создает запрос и извлекает результаты:
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();
}
}
Мы используем точный запрос из предыдущего раздела. Затем мы устанавливаем параметр электронной почты, чтобы сузить результаты. Наконец, мы получаем список результатов.
Давайте посмотрим, как мы можем извлечь отдельные объекты из полученного списка:
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
}
Мы перебираем полученный список и извлекаем объекты из заданного массива объектов. Имея в виду наш JPA-запрос и порядок сущностей в его разделе SELECT
, мы получаем сущность Channel
в качестве первого элемента, сущность Subscription
в качестве второго и сущность User
в качестве последнего элемента массива.
4. Вывод
В этой статье мы обсудили, как вернуть несколько сущностей в запросе JPA . Во-первых, мы создали пример, над которым работали позже в статье. Затем мы объяснили, как написать запрос JPA для возврата нескольких разных сущностей. Наконец, мы показали, как извлечь их из списка результатов.
Как всегда, полный исходный код статьи доступен на GitHub .