所以我的数据库中有 2 个实体
use async_graphql::{self, SimpleObject};
use chrono::NaiveDateTime;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, SimpleObject)]
#[sea_orm(table_name = "adverts")]
#[graphql(name = "Advert")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub available: bool,
pub price: f32,
pub location: String,
pub user_id: i32,
// pub adverts
}
#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
User,
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::User => Entity::belongs_to(super::user::Entity)
.from(Column::UserId)
.to(super::user::Column::Id)
.into(),
}
}
}
impl Related<super::user::Entity> for Entity {
fn to() -> RelationDef {
Relation::User.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
use async_graphql::{self, SimpleObject};
use chrono::NaiveDateTime;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, SimpleObject)]
#[sea_orm(table_name = "user")]
#[graphql(name = "User")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub name: String,
pub surname: String,
#[sea_orm(unique)]
pub email: String,
pub phone: String,
pub balance: f32,
#[graphql(visible = false)]
pub password_hash: String,
#[graphql(visible = false)]
pub refresh_token: Option<String>,
// pub adverts
}
#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {
Advert,
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Advert => Entity::has_many(super::advert::Entity).into(),
}
}
}
impl Related<super::advert::Entity> for Entity {
fn to() -> RelationDef {
Relation::Advert.def()
}
}
impl ActiveModelBehavior for ActiveModel {}
impl Entity {
pub fn find_by_email(email: String) -> Select<Entity> {
Self::find().filter(Column::Email.eq(email))
}
}
如您所见,我在它们之间有关系,我想提供向用户添加广告的功能,所以我编写了代码:
async fn create_advert(
&self,
ctx: &async_graphql::Context<'_>,
access_token: String,
price: f32,
location: String,
) -> Result<advert::Model, async_graphql::Error> {
let my_ctx = ctx.data::<Context>().unwrap();
let key: Hmac<Sha256> = match Hmac::new_from_slice(b"some-secret2") {
Ok(key) => key,
Err(err) => return Err(async_graphql::Error::new("Wrong token".to_string())),
};
let claims: BTreeMap<String, String> = match access_token.verify_with_key(&key) {
Ok(res) => res,
Err(err) => return Err(async_graphql::Error::new("Wrong token".to_string())),
};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as usize;
if claims["sub"] == "someone" && claims["exp"].parse::<usize>().unwrap() >= now {
let naive_date_time = Utc::now().naive_utc();
let advert = advert::ActiveModel {
available: Set(true),
user_id: Set(claims["id"].parse().unwrap()),
created_at: Set(naive_date_time),
updated_at: Set(naive_date_time),
price: Set(price),
location: Set(location),
..Default::default()
};
let advert: advert::Model = advert.insert(&my_ctx.db).await?;
return Ok(advert);
} else {
return Err(async_graphql::Error::new("Wrong token".to_string()));
}
}
当我在 graphql 中使用我的突变时,我收到错误:查询错误:从数据库返回的错误:关系“广告”不存在
所以问题是出了什么问题?
当我为 postgresql 表打开 erd 时,我可以看到这些表之间的关系:
我最后一次迁移:
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(User::Table)
.if_not_exists()
.col(
ColumnDef::new(User::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(User::CreatedAt).date_time().not_null())
.col(ColumnDef::new(User::UpdatedAt).date_time().not_null())
.col(ColumnDef::new(User::Name).string().not_null())
.col(ColumnDef::new(User::Surname).string().not_null())
.col(ColumnDef::new(User::Email).string().unique_key().not_null())
.col(ColumnDef::new(User::Phone).string().not_null())
.col(ColumnDef::new(User::Balance).float().not_null())
.col(ColumnDef::new(User::PasswordHash).string().not_null())
.col(ColumnDef::new(User::RefreshToken).string())
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(Advert::Table)
.if_not_exists()
.col(
ColumnDef::new(Advert::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Advert::CreatedAt).date_time().not_null())
.col(ColumnDef::new(Advert::UpdatedAt).date_time().not_null())
.col(ColumnDef::new(Advert::Available).boolean().not_null())
.col(ColumnDef::new(Advert::Price).float().not_null())
.col(ColumnDef::new(Advert::Location).string().not_null())
.col(ColumnDef::new(Advert::UserId).integer().not_null())
.foreign_key(
ForeignKey::create()
.name("fk-advert-user_id")
.from(Advert::Table, Advert::UserId)
.to(User::Table, User::Id),
)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(User::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Advert::Table).to_owned())
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum User {
Table,
Id,
CreatedAt,
UpdatedAt,
Name,
Surname,
Email,
Phone,
Balance,
PasswordHash,
RefreshToken,
}
#[derive(DeriveIden)]
enum Advert {
Table,
Id,
CreatedAt,
UpdatedAt,
Available,
Price,
Location,
UserId,
}
如果是这样,我正在使用seaorm,async_graphql + actix
我期待成功使用突变
好吧,这很愚蠢,所以问题是在我的数据库中我有一个名为 advert 的表 但这里是名字广告
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, SimpleObject)]
#[sea_orm(table_name = "adverts")] // here
#[graphql(name = "Advert")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub available: bool,
pub price: f32,
pub location: String,
pub user_id: i32,
// pub adverts
}
因此,如果有人遇到同样的问题,解决方案是将 sea orm table_name 更改为与数据库中相同的名称