diesel 是 rust世界的 持久层框架。 官方网址 diesel.rs (域名很有意思)
截止 2020-5-18 , 5500关注, 支持的数据库是 postgres, mysql , sqlite
一 创建数据库,表,映射,并查询数据
1. cargo new --lib test_diesel
会创建一个新文件夹: test_diesel
2. 修改Cargo.toml
[dependencies]
diesel = { version = "1.0.0", features = ["postgres"] }
dotenv = "0.9.0"
3. cargo install diesel_cli
4. 增加新文件: .env , 内容如下:
DATABASE_URL=mysql://root:666666@localhost/diesel_demo
5. $ diesel setup , 会分别创建一个文件夹和一个数据库
Creating migrations directory at: /workspace/test_rust/test_diesel2/migrations
Creating database: diesel_demo
6. 运行migration
diesel migration generate create_posts
分别增加对应的up/down.sql
up.sql: ( 这里是mysql的语句, 跟官方自带的postgres语句不太一样,稍有修改)
create table posts ( id int(11) not null auto_increment, title varchar(255) not null, body text, published boolean not null default false, primary key (`id`) )
down.sql:
drop database posts
7. 运行:
diesel migration run ( 回退的话,就用redo)
这个操作会自动的更新 src/schema.rs 的内容:
table! { posts (id) { id -> Integer, title -> Varchar, body -> Nullable<Text>, published -> Bool, } }
8. 连接数据库:
src/lib.rs
#[macro_use] extern crate diesel; extern crate dotenv; pub mod models; pub mod schema; use diesel::prelude::*; use dotenv::dotenv; use std::env; pub fn establish_connection() -> MysqlConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL") .expect("DATABASE_URL must be set"); MysqlConnection::establish(&database_url) .unwrap_or_else(|_| panic!("error connecting to {}", database_url)); }
9. 增加: src/models.rs 作为 持久层的映射。
// 这里的 order struct中的属性的顺序一定要跟 schema.rs 中的order表中的列的顺序一致。 #[derive(Queryable)] pub struct Order { pub id: i32, pub title: String, pub body: Option, pub published: bool, }
10. src/bin/show_posts.rs
src/bin/show_posts.rs // 声明需要用到的外部模块 extern crate test_diesel2; extern crate diesel; use self::test_diesel2::*; use self::models::*; use self::diesel::prelude::*; fn main(){ use test_diesel2::schema::posts::dsl::*; let connection = establish_connection(); let results = posts.filter(published.eq(true)) .limit(5) .load::(&connection) .expect("Error loading posts"); println!("Displaying {} posts", results.len()); for post in results { println!("======"); println!("{:?}", post.title); println!("{:?}", post.body); } }
11. 运行: cargo run ,就可以看到,读取数据库的内容了:
cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.03s Running `target/debug/show_posts` Displaying 0 posts
二. 我们开始创建新记录
修改 models.rs 增加以下内容:
use super::schema::posts; #[derive(Insertable)] #[table_name="posts"] pub struct NewPost<'a> { pub title: &'a str, pub body: &'a str, }
创建src/bin/write_post.rs , 增加以下内容:
extern crate test_diesel2; extern crate diesel; use self::test_diesel2::*; use std::io::{stdin, Read}; fn main() { let connection = establish_connection(); let post = create_post(&connection, "lalala", "I am the body"); println!(" saved title : lalaal with "); }
为 src/lib.rs 增加以下内容:
use self::models::{Post, NewPost}; pub fn create_post<'a>(conn: &MysqlConnection, title: &'a str, body: &'a str) { use schema::posts; let new_post = NewPost{ title: title, body: body, }; diesel::insert_into(posts::table) .values(&new_post) .execute(conn) .expect("Error saving new post"); }
运行:cargo run --bin write_post
就可以看到,内容被保存了。 ( 这里id 不会返回, 需要调用 select last_insert_id() 来 获得最新的id )