This topic describes how to build an application by using SeaORM and OceanBase Cloud. The application can perform basic operations, such as creating a table, inserting data, and querying data.
Environment preparation
Before you start, make sure that the following tools are installed:
- Rust 1.60 or later
- Cargo (Rust package manager)
- You have registered an account on OceanBase Cloud and created an instance and a MySQL-compatible tenant. For more information, see Create an instance and Create a tenant.
Create a new 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 the database connection
Create a .env file in the project root directory:
DATABASE_URL=mysql://`$user_name`:`$password`@$host:$port/$database_name
Parameter description:
$host: the connection address of OceanBase Cloud, for example,t********.********.oceanbase.cloud.$port: the connection port of OceanBase Cloud. The default value is 3306.$database_name: the name of the database to be accessed.$user_name: the account for accessing the database.$password: the password of the account.
Define entities
Create a src/entities directory and add mod.rs and user.rs files:
// 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 a src/db.rs file:
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 a src/user_service.rs file:
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),
}
}
// Get all users and print them
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
Expected output:
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