使用 rust diesel 插入记录时处理 id 的最佳方法是什么
what is the best way to handle the id when insert record using rust diesel
我正在使用 rust diesel(diesel = { version = "1.4.7", features = ["postgres","64-column-tables","chrono"] }
) 向 PostgreSQL 13 中插入一条记录,这是我的 rust 代码:
pub fn add_domain(request: &Json<AddDomainRequest>, login_user_info: LoginUserInfo) {
let connection = config::establish_connection();
let timestamp: i64 = get_current_millisecond();
let new_domain = Domain {
id: 0,
domain_name: request.domainName.to_string(),
domain_url: request.domainUrl.to_string(),
created_time: timestamp,
updated_time: timestamp,
cron: Some("* */1 * * * *".parse().unwrap()),
next_trigger_time: None,
monitor_status: None,
user_id: Option::from(login_user_info.userId),
expire_date: None,
days_before_trigger: 7,
notify_trigger_date: None,
expire_date_ms: None,
};
diesel::insert_into(crate::model::diesel::dolphin::dolphin_schema::domain::table)
.values(&new_domain)
.on_conflict_do_nothing()
.execute(&connection)
.unwrap();
}
我不知道如何处理主键id,域模型是自动生成的(意味着我不能修改域,因为它会覆盖下一次自动生成的修改),如果我删除id ,我无法新建域,如果我保留 id,PostgreSQL 数据库将显示此错误:
thread 'rocket-worker-thread' panicked at 'called `Result::unwrap()` on an `Err` value: DatabaseError(__Unknown, "cannot insert into column \"id\"")', src/service/app/cernitor/domain/domain_service.rs:46:10
>> Handler add panicked.
>> This is an application bug.
>> A panic in Rust must be treated as an exceptional event.
>> Panicking is not a suitable error handling mechanism.
>> Unwinding, the result of a panic, is an expensive operation.
>> Panics will severely degrade application performance.
>> Instead of panicking, return `Option` and/or `Result`.
>> Values of either type can be returned directly from handlers.
>> A panic is treated as an internal server error.
>> Outcome: Failure
>> No 500 catcher registered. Using Rocket default.
>> Response succeeded.
我应该怎么做才能让柴油机忽略自动生成的 ID?这是我的 table DDL:
CREATE TABLE public."domain" (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
domain_name varchar NOT NULL,
domain_url varchar NOT NULL,
created_time int8 NOT NULL,
updated_time int8 NOT NULL,
cron varchar NULL,
next_trigger_time timestamp(0) NULL,
monitor_status varchar NULL DEFAULT 1,
user_id int8 NULL,
expire_date timestamp NULL,
days_before_trigger int4 NOT NULL DEFAULT 14,
notify_trigger_date timestamp NULL GENERATED ALWAYS AS (expire_date - make_interval(days => days_before_trigger)) STORED,
expire_date_ms int8 NULL,
CONSTRAINT domain_record_pk PRIMARY KEY (id)
);
我试着像这样调整实体:
#[derive(Insertable,Queryable,Debug,Serialize,Deserialize,Default,Identifiable)]
#[primary_key(id)]
#[table_name = "domain"]
pub struct Domain {
pub id: i64,
pub domain_name: String,
pub domain_url: String,
pub created_time: i64,
pub updated_time: i64,
pub cron: Option<String>,
pub next_trigger_time: Option<NaiveDateTime>,
pub monitor_status: Option<String>,
pub user_id: Option<i64>,
pub expire_date: Option<NaiveDateTime>,
pub days_before_trigger: i32,
pub notify_trigger_date: Option<NaiveDateTime>,
pub expire_date_ms: Option<i64>,
}
还是没修好
要插入而不在 Domain
结构中添加 id
字段值,我们可以通过用 Option
类型
包装它来使 id 字段可选
#[derive(Default,Debug,Queryable,Identifiable,Insertable,Serialize,Deserialize)]
#[diesel(primary_key(id))]
#[table_name = "domain"]
pub struct Domain {
#[diesel(deserialize_as = "i64")]
pub id: Option<i64>,
pub domain_name: String,
pub domain_url: String,
pub created_time: i64,
pub updated_time: i64,
pub cron: Option<String>,
pub next_trigger_time: Option<NaiveDateTime>,
pub monitor_status: Option<String>,
pub user_id: Option<i64>,
pub expire_date: Option<NaiveDateTime>,
pub days_before_trigger: i32,
pub notify_trigger_date: Option<NaiveDateTime>,
pub expire_date_ms: Option<i64>,
}
然后在创建 Domain
实例时,我们可以将 None
作为值传递给 id
字段。
注:
#[diesel(deserialize_as = "i64")]
的解释
在使用 get_results
获取结果时,我们会遇到以下问题:
error[E0277]: the trait bound `Option<i64>: Queryable<BigInt, Pg>` is not satisfied
--> src/lib.rs:58:10
|
58 | .get_result(conn)
| ^^^^^^^^^^ the trait `Queryable<BigInt, Pg>` is not implemented for `Option<i64>`
|
该错误与 id
字段反序列化有关,其中指出 BigInt
无法直接反序列化为 Option<i64>
因为 id
字段在提取时是 i64
in Domain
struct and BigInt
is also internally i64
we told diesel to deserialize id
field as i64
with #[diesel(deserialize_as = "i64")]
instead of BigInt
然后可以映射为 Option<i64>
来解决问题
我正在使用 rust diesel(diesel = { version = "1.4.7", features = ["postgres","64-column-tables","chrono"] }
) 向 PostgreSQL 13 中插入一条记录,这是我的 rust 代码:
pub fn add_domain(request: &Json<AddDomainRequest>, login_user_info: LoginUserInfo) {
let connection = config::establish_connection();
let timestamp: i64 = get_current_millisecond();
let new_domain = Domain {
id: 0,
domain_name: request.domainName.to_string(),
domain_url: request.domainUrl.to_string(),
created_time: timestamp,
updated_time: timestamp,
cron: Some("* */1 * * * *".parse().unwrap()),
next_trigger_time: None,
monitor_status: None,
user_id: Option::from(login_user_info.userId),
expire_date: None,
days_before_trigger: 7,
notify_trigger_date: None,
expire_date_ms: None,
};
diesel::insert_into(crate::model::diesel::dolphin::dolphin_schema::domain::table)
.values(&new_domain)
.on_conflict_do_nothing()
.execute(&connection)
.unwrap();
}
我不知道如何处理主键id,域模型是自动生成的(意味着我不能修改域,因为它会覆盖下一次自动生成的修改),如果我删除id ,我无法新建域,如果我保留 id,PostgreSQL 数据库将显示此错误:
thread 'rocket-worker-thread' panicked at 'called `Result::unwrap()` on an `Err` value: DatabaseError(__Unknown, "cannot insert into column \"id\"")', src/service/app/cernitor/domain/domain_service.rs:46:10
>> Handler add panicked.
>> This is an application bug.
>> A panic in Rust must be treated as an exceptional event.
>> Panicking is not a suitable error handling mechanism.
>> Unwinding, the result of a panic, is an expensive operation.
>> Panics will severely degrade application performance.
>> Instead of panicking, return `Option` and/or `Result`.
>> Values of either type can be returned directly from handlers.
>> A panic is treated as an internal server error.
>> Outcome: Failure
>> No 500 catcher registered. Using Rocket default.
>> Response succeeded.
我应该怎么做才能让柴油机忽略自动生成的 ID?这是我的 table DDL:
CREATE TABLE public."domain" (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
domain_name varchar NOT NULL,
domain_url varchar NOT NULL,
created_time int8 NOT NULL,
updated_time int8 NOT NULL,
cron varchar NULL,
next_trigger_time timestamp(0) NULL,
monitor_status varchar NULL DEFAULT 1,
user_id int8 NULL,
expire_date timestamp NULL,
days_before_trigger int4 NOT NULL DEFAULT 14,
notify_trigger_date timestamp NULL GENERATED ALWAYS AS (expire_date - make_interval(days => days_before_trigger)) STORED,
expire_date_ms int8 NULL,
CONSTRAINT domain_record_pk PRIMARY KEY (id)
);
我试着像这样调整实体:
#[derive(Insertable,Queryable,Debug,Serialize,Deserialize,Default,Identifiable)]
#[primary_key(id)]
#[table_name = "domain"]
pub struct Domain {
pub id: i64,
pub domain_name: String,
pub domain_url: String,
pub created_time: i64,
pub updated_time: i64,
pub cron: Option<String>,
pub next_trigger_time: Option<NaiveDateTime>,
pub monitor_status: Option<String>,
pub user_id: Option<i64>,
pub expire_date: Option<NaiveDateTime>,
pub days_before_trigger: i32,
pub notify_trigger_date: Option<NaiveDateTime>,
pub expire_date_ms: Option<i64>,
}
还是没修好
要插入而不在 Domain
结构中添加 id
字段值,我们可以通过用 Option
类型
#[derive(Default,Debug,Queryable,Identifiable,Insertable,Serialize,Deserialize)]
#[diesel(primary_key(id))]
#[table_name = "domain"]
pub struct Domain {
#[diesel(deserialize_as = "i64")]
pub id: Option<i64>,
pub domain_name: String,
pub domain_url: String,
pub created_time: i64,
pub updated_time: i64,
pub cron: Option<String>,
pub next_trigger_time: Option<NaiveDateTime>,
pub monitor_status: Option<String>,
pub user_id: Option<i64>,
pub expire_date: Option<NaiveDateTime>,
pub days_before_trigger: i32,
pub notify_trigger_date: Option<NaiveDateTime>,
pub expire_date_ms: Option<i64>,
}
然后在创建 Domain
实例时,我们可以将 None
作为值传递给 id
字段。
注:
#[diesel(deserialize_as = "i64")]
在使用 get_results
获取结果时,我们会遇到以下问题:
error[E0277]: the trait bound `Option<i64>: Queryable<BigInt, Pg>` is not satisfied
--> src/lib.rs:58:10
|
58 | .get_result(conn)
| ^^^^^^^^^^ the trait `Queryable<BigInt, Pg>` is not implemented for `Option<i64>`
|
该错误与 id
字段反序列化有关,其中指出 BigInt
无法直接反序列化为 Option<i64>
因为 id
字段在提取时是 i64
in Domain
struct and BigInt
is also internally i64
we told diesel to deserialize id
field as i64
with #[diesel(deserialize_as = "i64")]
instead of BigInt
然后可以映射为 Option<i64>
来解决问题