Gymterview
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 содержит устаревшие данные.