Names the underlying-binding target for a GraphQL slot. The axis is determined by the directive site: column on a field or input field, column on a filter argument, database string (or Java enum constant) on an enum value.
SDL signature
directive @field(name: String!) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
|
|
(required) |
The target identifier. Resolves as a column name on |
Canonical example
The tutorial’s Customer type uses @field on every scalar to map GraphQL camelCase to PostgreSQL snake_case:
type Customer @table(name: "customer") {
firstName: String! @field(name: "FIRST_NAME")
lastName: String! @field(name: "LAST_NAME")
email: String @field(name: "EMAIL")
activebool: Boolean! @field(name: "ACTIVEBOOL")
}
A query selecting firstName lastName produces SELECT customer.first_name AS "firstName", customer.last_name AS "lastName". The selection set drives the projection: ask only for firstName and the SELECT shrinks to one column.
On an argument, @field steers the column the filter binds to when the GraphQL argument name doesn’t match the column name. From Query.customers:
type Query {
customers(active: Boolean @field(name: "ACTIVEBOOL")): [Customer!]!
}
Without the directive, the generator would look up a column called active on the customer table. Sakila’s customer table happens to have one (an unused integer flag), so the filter would silently bind to the wrong column. @field(name: "ACTIVEBOOL") pins it to the right one.
On an input field (a mutation), @field plays the same role:
input FilmCreateInput @table(name: "film") {
title: String! @field(name: "title")
languageId: Int! @field(name: "language_id")
}
The INSERT writes title and language_id; the GraphQL camelCase never reaches SQL.
On an enum value, @field maps the GraphQL value to the database string the value should encode as. See the mapping how-to for the enum case.
Root-value sigil: $source
In addition to a column or accessor name, the name argument admits one sigil literal: $source. It binds the SDL field to the upstream Java value taken as a whole, rather than to a member of it.
The sigil is admitted at exactly one site: the data field of a carrier-payload type returned by a @service-backed mutation. Anywhere else, @field(name: "$source") is rejected.
type Film @table(name: "film") {
title: String
}
type FilmListPayload {
films: [Film!] @field(name: "$source")
}
type Mutation {
runFilms: FilmListPayload
@service(service: {className: "com.example.FilmService", method: "getFilms"})
}
If FilmService.getFilms returns List<FilmRecord> (or Result<FilmRecord>), the films data field on the carrier payload is bound to that return value directly. The directive is a no-op confirmation of a binding the generator would otherwise infer implicitly; writing it makes the intent explicit and decouples the SDL slot name from the producer method’s signature.
The producer’s reflected return type must match the SDL element’s backing class. For a table-backed element, the producer must return the table’s record class (or List<RecordClass> / Result<RecordClass> when the SDL field is list-shaped); for a @record-backed element, the producer must return the declared record class with the same list-shape discipline. Mismatches fail the build with a typed message naming the producer and both types.
Unknown sigils are rejected at parse time: @field(name: "$foo") fails with Unknown sigil '$foo' on @field(name:); allowed: $source. The sigil at a non-admitted site fails with a message naming the only valid site.
Constraints
-
The
nameparameter is required; graphql-java rejects a no-arg@fieldat parse time. -
The target identifier must resolve in the surrounding `@table’s jOOQ catalog. The generator fails the build if the column does not exist.
-
When the GraphQL slot name and the target identifier match (case-insensitively), the directive is unnecessary. The example schema applies it explicitly anyway because mismatches are common in PostgreSQL projects and explicit binding keeps drift detectable.
See also
-
Tutorial page 2: The starter schema for
@fieldon regular type fields. -
Tutorial page 3: Running your first query explains the
@fieldargument-collision case. -
@tableestablishes the jOOQ table context that@fieldresolves against. -
@servicefor the mutation form that produces a carrier-payload type whose data field admits$source. -
How-to: Map types to tables for enum-value mappings and other patterns.