This topic introduces how to build an application by using SeaORM and OceanBase Database. It also covers the use of the application for fundamental database operations such as creating tables, inserting data, and querying data.
Environment preparation
Before you begin, make sure that you have installed the following tools:
- Rust 1.60 or later
- Cargo (the package manager of Rust)
- OceanBase Database V4.2.4 or later (MySQL-compatible mode) is installed and running.
Create a project
cargo new sea-orm-oceanbase-demo
cd sea-orm-oceanbase-demo
Add dependencies
Edit the Cargo.toml file and add the following dependencies:
[package]
name = "sea-orm-oceanbase-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
sea-orm = { version = "0.12", features = [
"sqlx-mysql",
"runtime-tokio-rustls",
"macros",
"with-json"
] }
sea-orm-migration = "0.12"
serde = { version = "1.0", features = ["derive"] }
dotenv = "0.15"
async-std = { version = "1.12", features = ["attributes"] }
chrono = "0.4"
Configure database connection
Create a .env file in the root directory of your project:
DATABASE_URL=mysql://username:password@localhost:2881/database_name
Define an entity
Create the src/entities directory and add files mod.rs and user.rs:
// src/entities/mod.rs
pub mod user;
// src/entities/user.rs
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub email: String,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
Database connection
Create src/db.rs:
use sea_orm::*;
use std::env;
use dotenv::dotenv;
pub async fn establish_connection() -> Result<DatabaseConnection, DbErr> {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
Database::connect(&database_url).await
}
Implement CRUD operations
Create src/user_service.rs:
use crate::entities::user;
use sea_orm::*;
use chrono::Utc;
pub struct UserService;
impl UserService {
// Create a user
pub async fn create_user(
db: &DatabaseConnection,
name: String,
email: String,
) -> Result<user::Model, DbErr> {
let new_user = user::ActiveModel {
name: Set(name),
email: Set(email),
created_at: Set(Utc::now()),
updated_at: Set(Utc::now()),
..Default::default()
};
new_user.insert(db).await
}
// Get a single user
pub async fn get_user(
db: &DatabaseConnection,
id: i32,
) -> Result<Option<user::Model>, DbErr> {
user::Entity::find_by_id(id).one(db).await
}
// Update a user
pub async fn update_user(
db: &DatabaseConnection,
id: i32,
name: Option<String>,
email: Option<String>,
) -> Result<user::Model, DbErr> {
let mut user: user::ActiveModel = user::Entity::find_by_id(id)
.one(db)
.await?
.ok_or_else(|| DbErr::Custom("User not found".to_owned()))?
.into();
if let Some(name) = name {
user.name = Set(name);
}
if let Some(email) = email {
user.email = Set(email);
}
user.updated_at = Set(Utc::now());
user.update(db).await
}
// Delete a user
pub async fn delete_user(
db: &DatabaseConnection,
id: i32,
) -> Result<DeleteResult, DbErr> {
let user: user::ActiveModel = user::Entity::find_by_id(id)
.one(db)
.await?
.ok_or_else(|| DbErr::Custom("User not found".to_owned()))?
.into();
user.delete(db).await
}
// Get all users
pub async fn get_all_users(
db: &DatabaseConnection,
) -> Result<Vec<user::Model>, DbErr> {
user::Entity::find().all(db).await
}
}
Main program
Modify src/main.rs:
mod entities;
mod db;
mod user_service;
use sea_orm::{DatabaseConnection, DbErr, Statement, ConnectionTrait};
use user_service::UserService;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Establish a database connection.
println!("Connecting to database...");
let db = db::establish_connection().await?;
println!("Database connected successfully!");
// Create tables (if they do not exist).
println!("Creating tables if not exist...");
create_tables(&db).await?;
println!("Tables created successfully!");
// Create users.
println!("Inserting sample data...");
let users_to_create = vec![
("Alice", "alice@example.com"),
("Bob", "bob@example.com"),
("Charlie", "charlie@example.com"),
];
for (name, email) in users_to_create {
println!("Creating user: {} <{}>", name, email);
match UserService::create_user(
&db,
name.to_string(),
email.to_string()
).await {
Ok(user) => println!("Created user: {} <{}>", user.name, user.email),
Err(e) => eprintln!("Error creating user: {}", e),
}
}
// Retrieve and print all users.
println!("\nCurrent users in database:");
match UserService::get_all_users(&db).await {
Ok(users) => {
for user in users {
println!("ID: {}, Name: {}, Email: {}, Created: {}, Updated: {}",
user.id, user.name, user.email, user.created_at, user.updated_at);
}
},
Err(e) => eprintln!("Error fetching users: {}", e),
}
Ok(())
}
async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
let stmt = r#"
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
"#;
db.execute(Statement::from_string(
db.get_database_backend(),
stmt.to_owned(),
))
.await?;
Ok(())
}
Run the program
cargo run
The expected return result is as follows:
Connecting to database...
Database connected successfully!
Creating tables if not exist...
Tables created successfully!
Inserting sample data...
Creating user: Alice <alice@example.com>
Creating user: Bob <bob@example.com>
Creating user: Charlie <charlie@example.com>
Current users in database:
ID: 1, Name: Alice, Email: alice@example.com, Created: 2025-05-27 09:47:01 UTC, Updated: 2025-05-27 09:47:01 UTC
ID: 2, Name: Bob, Email: bob@example.com, Created: 2025-05-27 09:47:01 UTC, Updated: 2025-05-27 09:47:01 UTC
ID: 3, Name: Charlie, Email: charlie@example.com, Created: 2025-05-27 09:47:01 UTC, Updated: 2025-05-27 09:47:01 UTC