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();
}
public static Bijection<CompanyId, String> bijection =
Bijection.of(CompanyId::value, CompanyId::new);
public static PgType<CompanyId> pgType =
PgTypes.text.to(Bijection.of(CompanyId::new, CompanyId::value));
public static 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.