[Rust SeaORM] Use sea-orm-cli to discover all tables in a database and generate a corresponding SeaORM entity file for each table

sea-orm-cli

SeaORM is a relational ORM to help you build light weight and concurrent web services in Rust

sea-orm-cli is a tool to discover all tables in a database and generate a corresponding SeaORM entity file for each table.

Using sea-orm-cli

First, install sea-orm-cli with cargo.

1
$ cargo install sea-orm-cli

Configure Environment

Setting DATABASE_URL in your environment, or create a .env file in your project root. Specify your database connection.

1
2
3
# .env

DATABASE_URL=sql://username:password@localhost/database

Getting Help

Use -h flag on any CLI command or subcommand for help.

1
2
3
4
5
6
7
8
# List all available commands
$ sea-orm-cli -h

# List all subcommands available in `generate` command
$ sea-orm-cli generate -h

# Show how to use `generate entity` subcommand
$ sea-orm-cli generate entity -h

Generating Entity Files

Discover all tables in a database and generate a corresponding SeaORM entity file for each table.

Generating Entity files from SQLite is not yet supported. You can write the entity files by hand, and then use the Entity to initialize a database.

Command line options:

  • -u / --database-url: database URL (default: DATABASE_URL specified in ENV)

  • -s / --database-schema: database schema (default: DATABASE_SCHEMA specified in ENV)

    • For MySQL, this argument is ignored

    • For PostgreSQL, this argument is optional with default value public

  • -o / --output-dir: entity file output directory (default: current directory)

  • -v / --verbose: print debug messages

  • --include-hidden-tables: generate entity files from hidden tables (table names starting with an underscore are ignored by default)

  • --compact-format: Generate entity file of compact format - https://www.sea-ql.org/SeaORM/docs/generate-entity/entity-structure/ (default: true)

    The expanded entity format can be generated by sea-orm-cli with the --compact-format option.

    Let’s look at a simple Cake entity.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    use sea_orm::entity::prelude::*;

    #[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
    #[sea_orm(table_name = "cake")]
    pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub name: String,
    }

    #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
    pub enum Relation {
    #[sea_orm(has_many = "super::fruit::Entity")]
    Fruit,
    }

    impl ActiveModelBehavior for ActiveModel {}
  • --expanded-format: Generate entity file of expanded format - https://www.sea-ql.org/SeaORM/docs/generate-entity/expanded-entity-structure/

    The expanded entity format can be generated by sea-orm-cli with the --expanded-format option.

    Let’s go through the sections of the expanded Cake entity.

    Entity

    By implementing the EntityTrait, you can perform CRUD operations on the given table.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
    pub struct Entity;

    impl EntityName for Entity {
    fn schema_name(&self) -> Option<&str> {
    None
    }

    fn table_name(&self) -> &str {
    "cake"
    }
    }

    Column

    An enum representing all columns in this table.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
    pub enum Column {
    Id,
    Name,
    }

    impl ColumnTrait for Column {
    type EntityName = Entity;

    fn def(&self) -> ColumnDef {
    match self {
    Self::Id => ColumnType::Integer.def(),
    Self::Name => ColumnType::String(None).def(),
    }
    }
    }

    Primary Key

    An enum representing the primary key of this table. If it is a composite key, then multiple enum variants can be added.

    The ValueType define the return type of last insert id in InsertResult.

    The auto_increment defines whether the primary key has an auto-generated value.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
    pub enum PrimaryKey {
    Id,
    }

    impl PrimaryKeyTrait for PrimaryKey {
    type ValueType = i32;

    fn auto_increment() -> bool {
    true

    Model

    The Rust struct for storing the query results.

    1
    2
    3
    4
    5
    #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
    pub struct Model {
    pub id: i32,
    pub name: String,
    }

    Active Model

    The ActiveModel has all the attributes of its corresponding Model but all attributes are wrapped in an ActiveValue.

    1
    2
    3
    4
    5
    #[derive(Clone, Debug, PartialEq)]
    pub struct ActiveModel {
    pub id: ActiveValue<i32>,
    pub name: ActiveValue<Option<String>>,
    }

    Relation

    Specifying the relations with other entities.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #[derive(Copy, Clone, Debug, EnumIter)]
    pub enum Relation {
    Fruit,
    }

    impl RelationTrait for Relation {
    fn def(&self) -> RelationDef {
    match self {
    Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
    }
    }
    }
  • --with-serde: Automatically derive serde Serialize / Deserialize traits for the entity (none, serialize, deserialize, both) (default: none)

1
2
3
4
5
# Generate entity files of database `bakery` to `src/entity`
$ sea-orm-cli generate entity \
-u sql://sea:sea@localhost/bakery \
-o src/entity \
--with-serde both

References

[1] Using sea-orm-cli | SeaORM - 🐚 An async & dynamic ORM for Rust - https://www.sea-ql.org/SeaORM/docs/generate-entity/sea-orm-cli

[2] SeaORM - 🐚 An async & dynamic ORM for Rust - https://www.sea-ql.org/SeaORM/

[3] SeaQL/sea-orm: 🐚 An async & dynamic ORM for Rust - https://github.com/SeaQL/sea-orm