Open Enums
Open enums use lookup tables with foreign keys to encode enum values. This pattern works across all databases, making it a portable alternative to native enum types.
When to Use Open Enumsβ
- Your database doesn't support native enums (Oracle, SQL Server)
- You need to add new enum values without regenerating code
- You want forwards compatibility with unknown values
- You need referential integrity enforced by the database
Schema Patternβ
CREATE TABLE title (code TEXT PRIMARY KEY);
INSERT INTO title (code) VALUES ('mr'), ('ms'), ('dr'), ('phd');
CREATE TABLE titled_person (
title TEXT NOT NULL REFERENCES title,
name TEXT NOT NULL
);
Configurationβ
Configure Typr to generate open enums:
val options = Options(
// ...
openEnums = Selector.relationNames("title")
)
Generated Codeβ
Typr generates an "open" enum type that accepts unknown values:
TitleId
public sealed interface TitleId permits TitleId.Unknown, TitleId.Known {
String value();
record Unknown(String value) implements TitleId {}
enum Known implements TitleId {
mr("mr"),
ms("ms"),
dr("dr"),
phd("phd");
final String value;
@Override
public String value() {
return value;
}
Known(String value) {
this.value = value;
}
}
java.util.Map<String, Known> ByName =
java.util.Arrays.stream(Known.values())
.collect(java.util.stream.Collectors.toMap(n -> n.value, n -> n));
static TitleId apply(String str) {
if (Known.ByName.containsKey(str)) {
return Known.ByName.get(str);
} else {
return new Unknown(str);
}
}
public static PgType<List<TitleId>> pgTypeArray =
PgTypes.text
.array()
.to(
Bijection.of(
xs -> xs.stream().map(TitleId::apply).toList(),
xs -> xs.stream().map(TitleId::value).toList()));
;
public static PgType<TitleId> pgType =
PgTypes.text.to(Bijection.of(TitleId::apply, TitleId::value));
;
}
The key difference from native enums: the Unknown case handles values not present at code generation time.
Supported Data Typesβ
Open enums support:
TEXT/VARCHARcolumns- Domain types with
TEXTas the base type