@Model

Use @Model on an abstract class that represents a stored entity.

lib/models.dart
@Model(name: 'users', as: #users)
abstract class _User {
  @Field(name: 'email')
  String get email;
}

The annotation constructor is:

const Model({
  String? name,
  List<IdSpec> primaryKey = const [GeneratedIdSpec()],
  Symbol? as,
})
  • name is the stored table, collection, or resource name when the engine uses one. If omitted, the generated schema derives a name from the model declaration.
  • as supplies the generated accessor name, such as dorm.users.
  • primaryKey declares generated or existing identity fields.

The default primary key is one generated String field named id.

Identity specifications

Model.primaryKey accepts IdSpec values. The concrete specifications are GeneratedIdSpec, DatabaseGeneratedIdSpec, and ExistingIdSpec.

GeneratedIdSpec

Use the default or an explicit GeneratedIdSpec when dORM or the selected engine generates the identity:

@Model(
  primaryKey: [
    GeneratedIdSpec(as: #id, name: 'id', type: String),
  ],
)
abstract class _User {
  @Field(name: 'email')
  String get email;
}

The constructor is:

const GeneratedIdSpec({
  Symbol as = #id,
  String name = 'id',
  Type type = String,
})

as is the generated Dart property name, name is the stored field name, and type is the Dart identity type. For a generated identity, the generator can optionally call a static $dorm$generateId method declared directly on the annotated class:

lib/models.dart
@Model(name: 'users', as: #users)
abstract class _User {
  static String $dorm$generateId(_User model, String generatedId) {
    return model.email;
  }

  @Field()
  String get email;
}

The method receives the intermediate model and the identity initially produced by the engine. It must return the final identity and is called only for engine-generated identities. Explicit identities and identities generated by a database are kept unchanged. The method must be static, declared directly on the annotated class, and have exactly two required positional parameters: the annotated class and the identity type declared by GeneratedIdSpec.

DatabaseGeneratedIdSpec

Use DatabaseGeneratedIdSpec when the database assigns the identity during the insert and returns it to the engine:

@Model(
  name: 'sequences',
  primaryKey: [DatabaseGeneratedIdSpec(as: #id, name: 'id', type: int)],
)
abstract class _Sequence {
  @Field()
  String get name;
}

The identity is not present in the Data input. The engine omits the key from the insert, reads the generated value from the backend response, and then constructs the returned Model. MySQL, PostgreSQL, SQLite, and explicitly mapped HTTP resources support this flow for supported single-key entities when the table or endpoint defines its own generated identity.

$dorm$generateId cannot be combined with DatabaseGeneratedIdSpec.

ExistingIdSpec

Use ExistingIdSpec when the primary-key field is already declared by the annotated class:

@Model(
  primaryKey: [
    ExistingIdSpec(referTo: #externalId),
  ],
)
abstract class _ImportedUser {
  @Field(name: 'external-id')
  String get externalId;
}

For a composite identity, provide multiple existing fields in their declared order:

@Model(
  primaryKey: [
    ExistingIdSpec(referTo: #userId),
    ExistingIdSpec(referTo: #productId),
  ],
)
abstract class _CartItem {
  @Field(name: 'user-id')
  String get userId;

  @Field(name: 'product-id')
  String get productId;
}

The generator preserves the order of composite key fields. Current generated repositories require Creation.explicit with a CompositeKey for composite creation; automatic creation requests are rejected statically by the generated creation type. The identity is part of the generated Model, while the generated Data value contains the input fields.

Each @Model produces generated data and model types, an entity with schema metadata, a repository accessor, and a relationship root when related fields are present. The generated accessors and repository types are described in the Generated output contract.

Use @Field, @ModelField, and @ForeignField on the model getters to describe its stored values.