SQL
Statements live in .sql files, and a comment block above each one says what to generate for it:
-- name: findTenant
-- returning: single
-- resultRowType: com.example.domain.Tenant
select id, slug, created_at
from tenant
where id = :id
name becomes the method, every :id becomes one of its arguments and the placeholder the driver
binds, and returning decides whether you get one row, many, or a stream. Nothing says what :id
is, because Tenant has an id component and the tenant table has an id column — either
answers. Name a type only where neither can.
What you get back
A statement returns one of three things, depending on what you tell it:
| You write | You get |
|---|---|
| nothing | a Map<String, Object> per row |
resultRowType: com.example.domain.Tenant | a Tenant, from a mapper written for you |
resultRowConverter: com.example.ToTenant | whatever your own converter returns |
returning then wraps that in Optional, List or Stream — or drops it for a write, which
answers with the number of rows it changed.
Where to go next
SQL files — how a file is laid out, how several statements share one, and every key the front matter accepts.
Structure — how files and directories decide which repository a statement lands in, and how to override that.
Converters
— how a row becomes something other than a Map. Naming a record is
usually all it takes; there is a hand-written escape hatch for mappings a record cannot express, and
the same types work for parameters on the way in.
Schema validation
— holding your statements to the create table statements your
project already keeps, so a column that does not exist fails the build rather than the request. It
also settles what a parameter’s type is, which is most of the front matter a write statement used to
need.
Transactions — running several statements on one connection, with plain JDBC or under a framework that opens the transaction for you.
Cookbook
— whole statements for the queries that need more than a name and a return
mode: IN lists, optional filters, pagination, streaming, nested records, enums, JSON columns,
batches, and one statement per database.