DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

I Built a Tool That Shows the SQL Behind Any Spring Data Method Name

Spring Data JPA has one genuinely magical feature: you declare a query by naming a method. No SQL, no @Query, no implementation.

interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByStatusAndCustomerOrderByCreatedAtDesc(OrderStatus status, String customer);
}
Enter fullscreen mode Exit fullscreen mode

Spring reads that name at startup and writes the query for you. It's wonderful — right up until you hit a method name and think "...wait, what does that actually generate?"

So I built a tool that shows you, live: type a method name, watch the JPQL and SQL appear.

▶ Live demo: https://dev48v.github.io/sql-to-jpa/
Source (zero dependencies): https://github.com/dev48v/sql-to-jpa

How the derivation works

Spring splits the method name into three parts:

find  By  StatusAndCustomer  OrderByCreatedAtDesc
└subject┘  └─── predicates ───┘ └──── sorting ────┘
Enter fullscreen mode Exit fullscreen mode
  1. Subjectfind / read / get / query / count / exists / delete, plus optional Distinct and Top/First limits.
  2. Predicates — properties joined by And / Or, each with an optional operator keyword.
  3. OrderBy — one or more properties, each Asc or Desc.

The example above becomes:

select o.* from orders o
where o.status = ? and o.customer = ?
order by o.created_at desc
Enter fullscreen mode Exit fullscreen mode

The keywords are the whole language

The operator is a suffix on the property name, and there are a lot of them:

Method fragment SQL
QuantityGreaterThan quantity > ?
CreatedAtBetween created_at between ? and ?
CustomerContaining `customer like '%'\
{% raw %}StatusIn status in (?)
ItemIsNull item is null
ActiveTrue active = true
CustomerIgnoreCase upper(customer) = upper(?)

A couple of things that trip people up, made visible in the tool:

  • Between and In change the parameter type. Between takes two args; In takes a Collection. The generated signature reflects that.
  • The return type comes from the subject. count…long, exists…boolean, findFirst…/findTop1…Optional<T>, otherwise List<T>.
  • Top3 adds a limit that lives in SQL, not JPQL.

Why type it out instead of reading the docs

The grammar is simple in principle and fiddly in practice — GreaterThanEqual vs GreaterThan, where IgnoreCase goes, what Containing does with %. Poking at a live parser and watching the SQL change as you edit the name is faster than scanning a reference table, and it sticks better.

It's one index.html, no build, no dependencies — best-effort over a sample Order entity with the default camelCase → snake_case column naming.

If this saved you a "what does this generate?" moment, a star helps others find it: https://github.com/dev48v/sql-to-jpa

Top comments (0)