Primary Key Types
For every table with a primary key, Typr generates a distinct ID type. This prevents mixing up IDs from different tables—a common source of bugs.
Simple Primary Keys
A table with a single-column primary key gets a wrapper type:
/** Type for the primary key of table `showcase.company` */
public record CompanyId(String value) {
public CompanyId withValue(String value) {
return new CompanyId(value);
}
@Override
public java.lang.String toString() {
return value.toString();
}
static public Bijection<CompanyId, String> bijection =
Bijection.of(CompanyId::value, CompanyId::new);
static public PgType<CompanyId> pgType =
PgTypes.text.to(Bijection.of(CompanyId::new, CompanyId::value));
static public PgType<List<CompanyId>> pgTypeArray =
pgType.array();
}
The wrapper ensures you can't accidentally pass a CustomerId where a CompanyId is expected. The compiler catches these mistakes.
Composite Primary Keys
Tables with multi-column primary keys get a composite ID type:
/** Type for the composite primary key of table `showcase.project_assignment` */
public record ProjectAssignmentId(
EmployeeId employeeId,
ProjectId projectId
) implements Tuple2<EmployeeId, ProjectId> {
public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {
return new ProjectAssignmentId(employeeId, projectId);
}
public ProjectAssignmentId withProjectId(ProjectId projectId) {
return new ProjectAssignmentId(employeeId, projectId);
}
public static RowCodec<ProjectAssignmentId> rowCodec = RowCodecs.of(EmployeeId.pgType, ProjectId.pgType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});
@Override
public EmployeeId _1() {
return employeeId;
}
@Override
public ProjectId _2() {
return projectId;
}
}
The composite type bundles all key columns together, making it easy to pass around and use in lookups.
Using ID Types
ID types integrate with repositories for type-safe lookups:
Optional<CompanyRow> selectById(
CompanyId id,
ConnectionRead c
);
Disabling ID Types
If you don't want wrapper types for certain tables, configure enablePrimaryKeyType:
Options options = new Options(
"mypkg",
Lang.Java,
// ... other options
Selector.relationNames("legacy_table"), // Only generate ID types for this table
);
Use Selector.All (default) for all tables, Selector.None to disable, or Selector.relationNames(...) for specific tables.
Composite ID types are always generated regardless of this setting.