Skip to content

✅ Mapping JDBC results to Java return types

SQL result methods return one of a few common shapes:

  • one column value
  • one named column value
  • one row object
  • many row objects
  • generated values from an update
  • a custom value created by a converter

Use a scalar return type for COUNT(*), flags, IDs, names, and other single-column results. When the SQL returns one column, Kaumei JDBC can map that value directly.

@JdbcSelect("SELECT COUNT(*) FROM db_customers")
int countCustomers();

Use @JdbcName on the method when the SQL returns several columns and the method should read one specific column. This applies to column results, not row objects.

@JdbcName("name")
@JdbcSelect("SELECT id, name FROM db_customers WHERE id = :id")
String customerName(long id);

For COUNT(*) and other single-column queries, a column name is usually not needed.

Use a record or class when one SQL row should become one Java object. Record components or constructor parameters are matched to JDBC column names.

enum PricingPlan {
FREE, BASIC, PRO, ENTERPRISE
}
record CustomerRow(long id,
String name,
Integer budge,
@JdbcName("pricing_plan") PricingPlan plan) {
}
@JdbcSelect("SELECT id, name, budge, pricing_plan FROM db_customers WHERE id = :id")
CustomerRow customer(long id);

Use @JdbcName on a record component or constructor parameter when the Java name does not match the SQL column name.

Use List<T>, Stream<T>, or JdbcIterable<T> when a query returns several rows. Each row is mapped like the single-row case.

@JdbcSelect("SELECT id, name, budge, pricing_plan FROM db_customers ORDER BY id")
List<CustomerRow> customers();

Use an update return type when the database returns generated values such as an ID or timestamp. Map generated columns like a normal result row.

record GeneratedCustomer(long id,
@JdbcName("created_at") LocalDateTime createdAt) {
}
@JdbcToJava
static LocalDateTime fromTimestamp(Timestamp value) {
return value.toLocalDateTime();
}
@JdbcUpdate(
value = "INSERT INTO db_customers (name, budge, pricing_plan) VALUES (:name, :budge, :plan)",
returnGeneratedValues = JdbcUpdate.GeneratedValues.DEFAULT)
GeneratedCustomer insertCustomer(String name, Integer budge, PricingPlan plan);

Use a named converter when one result method needs a special mapping strategy.

record UpperName(String value) {
}
@JdbcToJava("upper")
static UpperName upperName(String value) {
return new UpperName(value.toUpperCase());
}
@JdbcConverterName("upper")
@JdbcSelect("SELECT name FROM db_customers WHERE id = :id")
UpperName upperCustomerName(long id);

@JdbcConverterName on the result method selects the named @JdbcToJava converter for that method.

That is usually fine. For a single-column scalar result, Kaumei JDBC can map the first column directly.

Use @JdbcName on the method when the method returns one column from a result set with several columns. For row objects, put @JdbcName on the record component or constructor parameter that maps to the column.

Check that the selected SQL columns match the record components or constructor parameters. If a database column uses a different name, add @JdbcName to the component or parameter.

Use an unnamed @JdbcToJava converter for the normal mapping strategy of a type. Use a named converter only for special cases. Enums and suitable class or record constructors can be used as defaults.

Check that the generated columns returned by the database match the Java return type. For a generated row object, use @JdbcName when a generated column name differs from the Java name.

For exact result mapping rules, see result mapping. For exact converter lookup order, scopes, and fallback creation, see converter lookup. For select and update method rules, see JDBC select and JDBC update.