middle
Как использовать @Query, JPQL и native queries?
Когда query methods недостаточно, Spring Data предоставляет аннотацию @Query для написания собственных запросов.
JPQL (Java Persistence Query Language) оперирует сущностями и их полями, а не таблицами и колонками. Native queries используют обычный SQL.
JPQL
Пример
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmailAddress(@Param("email") String email);
@Query("SELECT u FROM User u JOIN u.roles r WHERE r.name = :roleName")
List<User> findByRoleName(@Param("roleName") String roleName);
@Query("SELECT new com.example.dto.UserSummary(u.id, u.firstName, u.email) " +
"FROM User u WHERE u.status = 'ACTIVE'")
List<UserSummary> findActiveUserSummaries(); // DTO-проекция
Native queries
Пример
@Query(value = "SELECT * FROM users WHERE email = :email", nativeQuery = true)
Optional<User> findByEmailNative(@Param("email") String email);
@Query(
value = "SELECT * FROM users WHERE status = :status",
countQuery = "SELECT COUNT(*) FROM users WHERE status = :status",
nativeQuery = true
)
Page<User> findByStatusNative(@Param("status") String status, Pageable pageable);
Модифицирующие запросы
Пример
@Modifying(clearAutomatically = true)
@Transactional
@Query("UPDATE User u SET u.status = :status WHERE u.lastLoginAt < :date")
int deactivateInactiveUsers(@Param("status") String status,
@Param("date") LocalDateTime date);
Когда что использовать
| Тип | Когда |
|---|---|
| Query methods | Простые запросы по 1-2 полям |
| JPQL | JOIN-ы, агрегация, DTO-проекции |
| Native SQL | Специфичные функции БД, оптимизация |
На собеседовании: важно знать разницу между JPQL и native SQL и когда применять каждый. Частая ошибка – забыть
@Modifyingдля UPDATE/DELETE или забыть@Transactionalдля модифицирующих запросов. Ещё ошибка – не указатьclearAutomatically = true, из-за чего persistence context содержит устаревшие данные.