Запросы соединения таблиц в JPA довольно распространены. Поскольку JPA позволяет определять пользовательские SQL-запросы на уровне репозиториев, реализация соединения таблиц с помощью пользовательских SQL-запросов довольно проста. Эта статья написана на основе предыдущей статьи Основы JPA, поэтому рекомендуется ознакомиться с ней, если вы не знакомы с JPA.
На основе предыдущей статьи мы создали два новых сущностных класса, как показано ниже:
Company.java
@Entity
@Data
@NoArgsConstructor
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String companyName;
private String description;
public Company(String name, String description) {
this.companyName = name;
this.description = description;
}
}
School.java
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class School {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String name;
private String description;
}
Предположим, что мы хотим получить информацию о Person по его идентификатору из таблицы person. Мы знаем, что информация о Person распределена по трем таблицам: Company
, School
и Person
. Поэтому для получения всей информации о Person нам потребуется выполнить запрос соединения таблиц.Сначала нам нужно создать объект DTO, который будет содержать необходимую информацию о Person. Мы назовем его UserDTO
и используем его для хранения и передачи нужных данных.
@Data
@NoArgsConstructor
@Builder(toBuilder = true)
@AllArgsConstructor
public class UserDTO {
private String name;
private int age;
private String companyName;
private String schoolName;
}
Теперь мы напишем метод для получения базовой информации о Person.
/**
* Запрос соединения таблиц
*/
@Query(value = "select new github.snailclimb.jpademo.model.dto.UserDTO(p.name, p.age, c.companyName, s.name) " +
"from Person p left join Company c on p.companyId = c.id " +
"left join School s on p.schoolId = s.id " +
"where p.id = :personId")
Optional<UserDTO> getUserInformation(@Param("personId") Long personId);
Можно заметить, что приведённые выше SQL-запросы не сильно отличаются от тех, которые мы обычно используем. Основное отличие заключается в использовании операции с объектом new
.
Если нам нужно получить текущую информацию о всех пользователях и реализовать пагинацию, то можно использовать следующий подход. Обратите внимание, что для реализации пагинации мы добавили свойство countQuery
в аннотации @Query
.
@Query(value = "select new github.snailclimb.jpademo.model.dto.UserDTO(p.name, p.age, c.companyName, s.name) " +
"from Person p left join Company c on p.companyId = c.id " +
"left join School s on p.schoolId = s.id ",
countQuery = "select count(p.id) " +
"from Person p left join Company c on p.companyId = c.id " +
"left join School s on p.schoolId = s.id ")
Page<UserDTO> getUserInformationList(Pageable pageable);
```Пример использования:
```java
// Параметры пагинации
PageRequest pageRequest = PageRequest.of(0, 3, Sort.Direction.DESC, "age");
Page<UserDTO> userInformationList = personRepository.getUserInformationList(pageRequest);
// Общее количество элементов
System.out.println(userInformationList.getTotalElements()); // 6
// Общее количество страниц
System.out.println(userInformationList.getTotalPages()); // 2
System.out.println(userInformationList.getContent());
Вот два наиболее часто используемых примера:
IN
BETWEEN
Конечно, существует множество других применений, которые вам стоит попробовать самостоятельно.
IN
Если вам нужно выбрать записи, соответствующие одному из нескольких значений, вы можете использовать запрос с оператором IN
. В контексте JPA это выглядит следующим образом:
@Query(value = "select new github.snailclimb.jpademo.model.dto.UserDTO(p.name,p.age,c.companyName,s.name) " +
"from Person p left join Company c on p.companyId=c.id " +
"left join School s on p.schoolId=s.id " +
"where p.name IN :peopleList")
List<UserDTO> filterUserInfo(List peopleList);
Пример использования:
List<String> personList = new ArrayList<>(Arrays.asList("person1", "person2"));
List<UserDTO> userDTOS = personRepository.filterUserInfo(personList);
BETWEEN
Запрос, который находит значения, соответствующие определенному диапазону. Например, следующий метод реализует запрос для поиска информации о людях, возраст которых находится в определенном диапазоне.```java @Query(value = "select new github.snailclimb.jpademo.model.dto.UserDTO(p.name,p.age,c.companyName,s.name) " + "from Person p left join Company c on p.companyId=c.id " + "left join School s on p.schoolId=s.id " + "where p.age between :small and :big") List filterUserInfoByAge(int small, int big);
Практическое использование:
```java
List<UserDTO> userDTOS = personRepository.filterUserInfoByAge(19, 20);
В этом разделе мы изучили следующие ключевые моменты:
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )