Что такое нативные SQL-запросы в JPA и когда их стоит использовать?

«Что такое нативные SQL-запросы в JPA и когда их стоит использовать?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нативные запросы в JPA — это SQL-запросы, написанные на диалекте конкретной СУБД, которые выполняются напрямую, минуя механизмы преобразования JPQL/HQL. Они предоставляют полный контроль над синтаксисом запроса.

Когда использовать нативные запросы:

  • Для сложных JOIN-операций или оконных функций, которые сложно или невозможно выразить в JPQL.
  • Для использования специфичных для СУБД возможностей (например, JSON-функции в PostgreSQL, MERGE в Oracle).
  • Для оптимизации критичных по производительности запросов, где требуется точный контроль над планом выполнения.

Примеры использования:

  1. С помощью EntityManager:

    @PersistenceContext
    private EntityManager entityManager;
    
    public List<User> findUsersOlderThan(int age) {
        // :age - именованный параметр для защиты от SQL-инъекций
        String sql = "SELECT * FROM users WHERE age > :age";
        Query query = entityManager.createNativeQuery(sql, User.class);
        query.setParameter("age", age);
        return query.getResultList();
    }
  2. С помощью Spring Data JPA и аннотации @Query:

    @Repository
    public interface UserRepository extends JpaRepository<User, Long> {
        // Атрибут nativeQuery = true указывает на нативный запрос
        @Query(value = "SELECT * FROM users u WHERE u.status = :status", nativeQuery = true)
        List<User> findByStatusNative(@Param("status") String status);
    }
Преимущества и недостатки: Преимущество Недостаток
Полный контроль над SQL. Можно использовать любой синтаксис СУБД. Потеря переносимости. Запрос привязан к конкретной СУБД.
Возможность тонкой оптимизации. Сложность поддержки. Запросы не проверяются на этапе компиляции.
Прямой доступ ко всем функциям БД. Риск SQL-инъекций при неправильном использовании (всегда используйте параметризацию!).
Отсутствие пагинации "из коробки" для сложных запросов (требует ручной доработки).