Repository
ModelRepository implements the Repository<T, ID> trait and provides the standard set of create, read, update, and delete operations for a model type. Obtain one from any #[derive(Model)] struct using User::repository(&mut conn).
Obtaining a repository
use rust_web_server::model::DbPool;
let pool = DbPool::from_env()?;let mut conn = pool.get()?;
// User::repository is generated by #[derive(Model)]let mut repo = User::repository(&mut *conn);The repository borrows the connection mutably for its lifetime, so only one repository can be active at a time per connection.
Repository<T, ID> trait
pub trait Repository<T: Model, ID> { fn find_by_id(&mut self, id: ID) -> Result<Option<T>, DbError>; fn find_all(&mut self) -> Result<Vec<T>, DbError>; fn save(&mut self, entity: &T) -> Result<T, DbError>; fn save_all(&mut self, entities: &[T]) -> Result<Vec<T>, DbError>; fn delete_by_id(&mut self, id: ID) -> Result<(), DbError>; fn delete_all_by_id(&mut self, ids: &[ID]) -> Result<(), DbError>; fn count(&mut self) -> Result<i64, DbError>; fn exists_by_id(&mut self, id: ID) -> Result<bool, DbError>;}The ID type is always i64 for the built-in ModelRepository implementation.
Method reference
find_by_id
Executes SELECT * FROM users WHERE id = ? and returns the first matching row, or None if no row exists.
match repo.find_by_id(42)? { Some(user) => println!("found: {}", user.email), None => println!("not found"),}find_all
Executes SELECT * FROM users and returns every row in the table.
let all_users: Vec<User> = repo.find_all()?;Use the Query Builder when you need filtering, ordering, or pagination.
save
Inserts or updates a single entity.
- INSERT — when the primary key field is
0(orValue::Null), or when#[primary_key(auto_increment)]is set and the pk is zero. - UPDATE — when the primary key is non-zero.
save returns the persisted entity with the primary key filled in (important for auto-increment inserts).
let mut user = User { id: 0, // 0 triggers INSERT with auto_increment name: "Alice".into(), email: "alice@example.com".into(), role: "user".into(), active: true, score: 0.0, bio: None, display_label: String::new(),};
let saved = repo.save(&user)?;println!("new id: {}", saved.id); // id assigned by the databaseTo update, set a non-zero primary key:
let updated = repo.save(&User { id: saved.id, role: "admin".into(), ..saved })?;save_all
Calls save for each entity in the slice, returning a Vec<T> of the persisted entities.
let users = vec![ User { id: 0, name: "Bob".into(), email: "bob@example.com".into(), .. }, User { id: 0, name: "Carol".into(), email: "carol@example.com".into(), .. },];let saved = repo.save_all(&users)?;delete_by_id
Executes DELETE FROM users WHERE id = ?.
repo.delete_by_id(42)?;delete_all_by_id
Calls delete_by_id for each id in the slice (one DELETE per id).
repo.delete_all_by_id(&[1, 2, 3])?;count
Executes SELECT COUNT(*) FROM users and returns the result as i64.
let total: i64 = repo.count()?;println!("{total} users in database");exists_by_id
Returns true if a row with the given id exists.
if repo.exists_by_id(99)? { println!("user 99 exists");}Internally calls find_by_id and checks for Some.
Auto-increment PK retrieval
After an INSERT, the newly assigned primary key is retrieved differently per backend:
| Backend | Mechanism |
|---|---|
| SQLite | last_insert_rowid() |
| PostgreSQL | INSERT … RETURNING id |
| MySQL | last_insert_id() |
In all cases, save re-fetches the inserted row via SELECT * FROM … WHERE id = ? and returns the complete, database-consistent entity.
Full CRUD example
use rust_web_server::model::{DbPool, Repository};use rust_web_server::Model;
#[derive(Model, Debug, Clone)]#[table(name = "users")]pub struct User { #[primary_key(auto_increment)] pub id: i64, #[column(name = "first_name")] pub name: String, #[column(unique)] pub email: String, pub role: String, pub active: bool,}
fn main() -> Result<(), Box<dyn std::error::Error>> { let pool = DbPool::from_env()?; let mut conn = pool.get()?; let mut repo = User::repository(&mut *conn);
// CREATE let alice = repo.save(&User { id: 0, name: "Alice".into(), email: "alice@example.com".into(), role: "user".into(), active: true, })?; println!("created user #{}", alice.id);
// READ let found = repo.find_by_id(alice.id)?.expect("user exists"); println!("fetched: {} ({})", found.name, found.email);
// UPDATE let promoted = repo.save(&User { role: "admin".into(), ..found })?; println!("role is now: {}", promoted.role);
// EXISTS / COUNT println!("exists: {}", repo.exists_by_id(alice.id)?); println!("total: {}", repo.count()?);
// DELETE repo.delete_by_id(alice.id)?; println!("deleted");
Ok(())}