添加 r2d2 和 r2d2_mysql 依赖,重构数据库连接池,更新用户服务接口以支持新的连接管理

This commit is contained in:
rsgl 2024-11-15 23:32:18 +08:00
parent fffc761108
commit 5c8ac42e8a
8 changed files with 239 additions and 129 deletions

12
.idea/dataSources.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="test_server@122.152.201.90" uuid="23e14647-d640-43e8-a7af-9a251a179112">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://122.152.201.90:9912/test_server</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

6
.idea/sqldialects.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="MySQL" />
</component>
</project>

32
Cargo.lock generated
View File

@ -698,6 +698,8 @@ dependencies = [
"actix-web",
"bcrypt",
"mysql",
"r2d2",
"r2d2_mysql",
"serde",
"serde_derive",
"uuid",
@ -1742,6 +1744,27 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "r2d2"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
dependencies = [
"log",
"parking_lot",
"scheduled-thread-pool",
]
[[package]]
name = "r2d2_mysql"
version = "25.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93963fe09ca35b0311d089439e944e42a6cb39bf8ea323782ddb31240ba2ae87"
dependencies = [
"mysql",
"r2d2",
]
[[package]]
name = "radium"
version = "0.7.0"
@ -1931,6 +1954,15 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "scheduled-thread-pool"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
dependencies = [
"parking_lot",
]
[[package]]
name = "scopeguard"
version = "1.2.0"

View File

@ -5,6 +5,8 @@ edition = "2021"
[dependencies]
mysql = "25.0.1"
r2d2 = "0.8.10"
r2d2_mysql = "25.0.0"
actix-web = "4"
serde = "1.0"
serde_derive = "1.0"

View File

@ -1,109 +1,120 @@
use crate::models::user::User;
use mysql::params;
use mysql::prelude::Queryable;
use r2d2::Pool;
use r2d2_mysql::MySqlConnectionManager;
/**
*
*/
pub fn create_user(conn: &mut mysql::PooledConn, user: &User) -> Result<(), mysql::Error> {
conn.exec_drop(
r"INSERT INTO users (id, name, age, email, password) VALUES (:id, :name, :age, :email, :password)",
params! {
"id" => &user.id,
"name" => &user.name,
"age" => &user.age,
"email" => &user.email,
"password" => &user.password,
},
)
pub struct UserRepository<'a> {
pub pool: &'a mut Pool<MySqlConnectionManager>,
}
/**
*
*/
pub fn delete_user(conn: &mut mysql::PooledConn, user: &User) -> Result<(), mysql::Error> {
conn.exec_drop(
r"DELETE FROM users WHERE id = :id",
params! {
"id" => &user.id,
},
)
}
impl<'a> UserRepository<'a> {
pub fn new(pool: &'a mut Pool<MySqlConnectionManager>) -> UserRepository {
UserRepository { pool }
}
/**
*
*/
pub fn update_user(conn: &mut mysql::PooledConn, user: &User) -> Result<(), mysql::Error> {
conn.exec_drop(
r"UPDATE users SET name = :name, age = :age, email = :email, password = :password WHERE id = :id",
params! {
"id" => &user.id,
"name" => &user.name,
"age" => &user.age,
"email" => &user.email,
"password" => &user.password,
},
)
}
/**
*
*/
pub fn create_user(&mut self, user: &User) -> Result<(), mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.exec_drop(
r"INSERT INTO users (id, name, age, email, password) VALUES (:id, :name, :age, :email, :password)",
params! {
"id" => &user.id,
"name" => &user.name,
"age" => &user.age,
"email" => &user.email,
"password" => &user.password,
},
)
}
/**
*
*/
pub fn query_all_user(conn: &mut mysql::PooledConn) -> Result<Vec<User>, mysql::Error> {
conn.query_map(
"SELECT id, name, age, email, password FROM users",
|(id, name, age, email, password)| User {
id,
name,
age,
email,
password,
},
)
}
/**
*
*/
pub fn delete_user(&mut self, user: &User) -> Result<(), mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.exec_drop(
r"DELETE FROM users WHERE id = :id",
params! {
"id" => &user.id,
},
)
}
/**
* ID查询用户
*/
pub fn query_user_by_id(
conn: &mut mysql::PooledConn,
id: i32,
) -> Result<Option<User>, mysql::Error> {
let result: Option<User> = conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE id = :id",
params! {
"id" => id,
},
)?;
Ok(result)
}
/**
*
*/
pub fn update_user(&mut self, user: &User) -> Result<(), mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.exec_drop(
r"UPDATE users SET name = :name, age = :age, email = :email, password = :password WHERE id = :id",
params! {
"id" => &user.id,
"name" => &user.name,
"age" => &user.age,
"email" => &user.email,
"password" => &user.password,
},
)
}
/**
*
*/
pub fn query_user_by_name(
conn: &mut mysql::PooledConn,
name: &str,
) -> Result<Option<User>, mysql::Error> {
conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE name = :name",
params! {
"name" => name,
},
)
}
/**
*
*/
/**
*
*/
pub fn query_user_by_email(
conn: &mut mysql::PooledConn,
email: &str,
) -> Result<Option<User>, mysql::Error> {
conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE email = :email",
params! {
"email" => email,
},
)
pub fn query_all_user(&mut self) -> Result<Vec<User>, mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.query_map(
"SELECT id, name, age, email, password FROM users",
|(id, name, age, email, password)| User {
id,
name,
age,
email,
password,
},
)
}
/**
* ID查询用户
*/
pub fn query_user_by_id(&mut self, id: i32) -> Result<Option<User>, mysql::Error> {
let mut conn = self.pool.get().unwrap();
let result: Option<User> = conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE id = :id",
params! {
"id" => id,
},
)?;
Ok(result)
}
/**
*
*/
pub fn query_user_by_name(&mut self, name: &str) -> Result<Option<User>, mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE name = :name",
params! {
"name" => name,
},
)
}
/**
*
*/
pub fn query_user_by_email(&mut self, email: &str) -> Result<Option<User>, mysql::Error> {
let mut conn = self.pool.get().unwrap();
conn.exec_first(
"SELECT id, name, age, email, password FROM users WHERE email = :email",
params! {
"email" => email,
},
)
}
}

View File

@ -2,6 +2,7 @@ use crate::models::user::User;
use crate::services::user_service;
use crate::utils::pool;
use actix_web::{get, post, web, HttpResponse, Responder};
use serde::Deserialize;
pub(crate) fn register(config: &mut web::ServiceConfig) {
config.service(register_user);
@ -13,10 +14,18 @@ pub(crate) fn register(config: &mut web::ServiceConfig) {
config.service(delete_user);
}
#[derive(Deserialize)]
struct RegisterUser {
name: String,
age: i32,
email: String,
password: String,
}
#[post("/user/register")]
async fn register_user(user: web::Json<User>) -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
async fn register_user(user: web::Json<RegisterUser>) -> impl Responder {
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
let mut new_user = User {
id: 0,
name: user.name.clone(),
@ -25,13 +34,13 @@ async fn register_user(user: web::Json<User>) -> impl Responder {
password: user.password.clone(),
};
user_service::create_user(&mut conn, &mut new_user).unwrap();
HttpResponse::Ok().json("User registered successfully")
HttpResponse::Ok().json("SUCCESS")
}
#[get("/user/query_all_user")]
async fn query_all_user() -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
let users = user_service::query_all_user(&mut conn).unwrap();
HttpResponse::Ok().json(users)
}
@ -39,8 +48,8 @@ async fn query_all_user() -> impl Responder {
#[get("/user/{id}")]
async fn query_user_by_id(path: web::Path<i32>) -> impl Responder {
let id = path.into_inner();
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
match user_service::query_user_by_id(&mut conn, id) {
Ok(user) => HttpResponse::Ok().json(user),
@ -50,8 +59,8 @@ async fn query_user_by_id(path: web::Path<i32>) -> impl Responder {
#[get("/user/{email}")]
async fn query_user_by_email(path: web::Path<String>) -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
let email = path.into_inner();
match user_service::query_user_by_email(&mut conn, email.as_str()) {
Ok(user) => HttpResponse::Ok().json(user),
@ -61,8 +70,8 @@ async fn query_user_by_email(path: web::Path<String>) -> impl Responder {
#[get("/user/{name}")]
async fn query_user_by_name(path: web::Path<String>) -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
let name = path.into_inner();
match user_service::query_user_by_name(&mut conn, name.as_str()) {
Ok(user) => HttpResponse::Ok().json(user),
@ -72,16 +81,16 @@ async fn query_user_by_name(path: web::Path<String>) -> impl Responder {
#[post("/user/update")]
async fn update_user(user: web::Json<User>) -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
user_service::update_user(&mut conn, &user).unwrap();
HttpResponse::Ok().json("User updated successfully")
}
#[post("/user/delete")]
async fn delete_user(user: web::Json<User>) -> impl Responder {
let pool = pool::get_db_pool();
let mut conn = pool.get_conn().unwrap();
let pool = pool::get_database_pool().unwrap();
let mut conn = pool.get().unwrap();
user_service::delete_user(&mut conn, &user).unwrap();
HttpResponse::Ok().json("User deleted successfully")
}

View File

@ -2,39 +2,58 @@ use crate::models::user::User;
use crate::repositories::user_repository;
use bcrypt::{hash, DEFAULT_COST};
use mysql;
use mysql::PooledConn;
use r2d2::PooledConnection;
use r2d2_mysql::{MySqlConnectionManager, mysql::PooledConn};
/**
*
*/
pub fn create_user(conn: &mut PooledConn, user: &mut User) -> Result<(), mysql::Error> {
user.password = hash(&user.password, DEFAULT_COST).unwrap();
user_repository::create_user(conn, user)
pub fn create_user(
conn: &mut PooledConn,
user: &mut User,
) -> Result<(), mysql::Error> {
let mut new_user = User {
password: hash(&user.password, DEFAULT_COST).unwrap(),
..user.clone()
};
user_repository::create_user(conn, &mut new_user)
}
/**
*
*/
pub fn query_all_user(conn: &mut PooledConn) -> Result<Vec<User>, mysql::Error> {
pub fn query_all_user(
conn: &mut PooledConnection<MySqlConnectionManager>,
) -> Result<Vec<User>, mysql::Error> {
user_repository::query_all_user(conn)
}
pub fn query_user_by_id(conn: &mut PooledConn, id: i32) -> Result<Option<User>, mysql::Error> {
pub fn query_user_by_id(
conn: &mut PooledConnection<MySqlConnectionManager>,
id: i32,
) -> Result<Option<User>, mysql::Error> {
user_repository::query_user_by_id(conn, id)
}
pub fn query_user_by_email(
conn: &mut PooledConn,
conn: &mut PooledConnection<MySqlConnectionManager>,
email: &str,
) -> Result<Option<User>, mysql::Error> {
user_repository::query_user_by_email(conn, email)
}
pub fn query_user_by_name(conn: &mut PooledConn, name: &str) -> Result<Option<User>, mysql::Error> {
pub fn query_user_by_name(
conn: &mut PooledConnection<MySqlConnectionManager>,
name: &str,
) -> Result<Option<User>, mysql::Error> {
user_repository::query_user_by_name(conn, name)
}
pub fn update_user(conn: &mut PooledConn, user: &User) -> Result<(), mysql::Error> {
pub fn update_user(
conn: &mut PooledConnection<MySqlConnectionManager>,
user: &User,
) -> Result<(), mysql::Error> {
if user_repository::query_user_by_id(conn, user.id)?.is_none() {
return Err(mysql::Error::MySqlError(mysql::MySqlError {
code: 1062,
@ -46,7 +65,10 @@ pub fn update_user(conn: &mut PooledConn, user: &User) -> Result<(), mysql::Erro
user_repository::update_user(conn, user)
}
pub fn delete_user(conn: &mut PooledConn, user: &User) -> Result<(), mysql::Error> {
pub fn delete_user(
conn: &mut PooledConnection<MySqlConnectionManager>,
user: &User,
) -> Result<(), mysql::Error> {
if user_repository::query_user_by_id(conn, user.id)?.is_none() {
return Err(mysql::Error::MySqlError(mysql::MySqlError {
code: 1062,

View File

@ -1,9 +1,25 @@
use mysql::*;
// use mysql::*;
/**
*
*/
pub fn get_db_pool() -> Pool {
// /**
// * 获取数据库连接池
// */
// pub fn get_database_pool().unwrap -> Pool {
// let url = "mysql://root:0andrx@122.152.201.90:9912/test_server";
// Pool::new(url).expect("TODO: panic message")
// }
use r2d2::Pool;
use r2d2_mysql::MySqlConnectionManager;
pub fn get_database_pool() -> Result<Pool<MySqlConnectionManager>, r2d2::Error> {
let url = "mysql://root:0andrx@122.152.201.90:9912/test_server";
Pool::new(url).expect("TODO: panic message")
let opts =
r2d2_mysql::mysql::OptsBuilder::from_opts(r2d2_mysql::mysql::Opts::from_url(url).unwrap());
let manager = r2d2_mysql::MySqlConnectionManager::new(opts);
let pool = Pool::builder()
.max_size(10)
.min_idle(Some(5))
.build(manager)
.unwrap();
Ok(pool)
}