Models & Codegen
Models are the heart of your application. In Ormed, models are simple Dart classes annotated with @OrmModel.
Prerequisites
What You’ll Learn
- How to define core domain models for the tutorial app
- How relations are expressed with Ormed annotations
- How model definitions feed code generation
Step Outcome
By the end of this page, you should have:
GenreandMoviemodel classes with relation metadata- Generated ORM artifacts (
*.orm.dart) for query/repository usage - Generated DTOs used by seeders and HTTP handlers
Model Rules Used In This Tutorial
- Keep model classes declarative: fields + annotations only.
- Put relation metadata on ignored fields (
@OrmField(ignore: true)). - Use generated DTOs for writes (
InsertDto/UpdateDto) instead of ad-hoc maps in handlers.
Define the models
We'll define two models: Genre and Movie.
The Genre Model
The Genre model represents a category of movies. It uses an auto-incrementing integer as its primary key.
- Genre
(table: 'genres')
class Genre extends Model<Genre> {
const Genre({
required this.id,
required this.name,
this.description,
this.createdAt,
this.updatedAt,
});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String name;
final String? description;
final DateTime? createdAt;
final DateTime? updatedAt;
}
The Movie Model
The Movie model represents a film. It has a relationship with Genre.
Key annotations used here:
@OrmModel(table: 'movies'): Maps the class to themoviestable.@OrmField(isPrimaryKey: true, autoIncrement: true): Defines the primary key.@OrmRelation.belongsTo: Defines a "Many-to-One" relationship. We mark the field with@OrmField(ignore: true)because the relationship itself isn't a column; thegenre_idforeign key is.
- Movie
const Movie({
required this.id,
required this.title,
required this.releaseYear,
this.summary,
this.posterPath,
this.genreId,
this.createdAt,
this.updatedAt,
});
(isPrimaryKey: true, autoIncrement: true)
final int id;
final String title;
final int releaseYear;
final String? summary;
final String? posterPath;
final int? genreId;
(ignore: true)
.belongsTo(target: Genre, foreignKey: 'genre_id')
final Genre? genre = null;
final DateTime? createdAt;
final DateTime? updatedAt;
Generate ORM code + DTOs
Ormed uses code generation to provide type-safe queries and Data Transfer Objects (DTOs). Run the following command to generate the necessary code:
dart run build_runner build --delete-conflicting-outputs
What Gets Generated?
When you run build_runner, Ormed generates several artifacts:
-
Type Aliases (
$Movie,$Genre): These are type aliases used with Ormed's query builder. When you calldataSource.query<$Movie>(), you're telling Ormed which model you want to query. -
Insert DTOs (
MovieInsertDto): Used for creating new records. Only includes fields that should be set during creation. -
Update DTOs (
MovieUpdateDto): Used for updating existing records. All fields are optional, so you only update what changes. -
ORM Registry: A central registry that maps all your models to their table definitions.
Why DTOs?
The generator creates specialized DTOs like MovieInsertDto and MovieUpdateDto. We use these for database operations instead of the main model classes. This provides several benefits:
- Clarity: It's clear which fields are required for an insert vs. an update.
- Safety: You can't accidentally try to update a primary key or a read-only field.
- Validation: DTOs can have their own validation logic.
Verify Before Continuing
You should now see generated files beside your models (for example movie.orm.dart, genre.orm.dart) and no analyzer errors.