@Query

Basic Spring
≈ 2 min read

When it is better to write the query explicitly

If a condition no longer fits comfortably into a method name, you can attach a query to the method with @Query. By default, the string inside the annotation is JPQL, so it uses entity names and their fields, not database table and column names.

interface CustomerRepository extends JpaRepository<Customer, Long> {
    @Query("""
            select c
            from Customer c
            where c.active = true
              and c.age >= :minAge
            order by c.name
            """)
    List<Customer> findActiveAdults(@Param("minAge") int minAge);
}

The :minAge parameter is bound to the method argument through @Param. This declaration is easy to read: the method contract remains in the repository, while the whole query is visible instead of turning into a long sequence of words in the method name.

JPQL and native SQL are different levels

For most entity queries, staying at the JPQL level is convenient. But @Query can also execute native SQL when you need a database-specific feature or when a query is easier to express directly in terms of tables. In that case, the query depends on the real schema and SQL dialect more strongly than ordinary JPQL does.

@Query does not make a query string safe for arbitrary text substitution. Pass values as parameters, as in the example, instead of assembling a query by concatenating user input.