node.js - TypeORM AfterInsert() 无法在另一个表中添加 userId

标签 node.js typeorm

我有一个用户实体:

@Entity()
export class User extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  //...

  @OneToOne(() => UserActive)
  userActive: UserActive;

  @AfterInsert()
  public async handleAfterInsert() {
    const userActive = new UserActive();
    userActive.token = randomString();
    userActive.user = this;
    await getConnection().getRepository(UserActive).save(userActive);
  }
}

UserActive:

export class UserActive extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({
    length: 25,
    unique: true,
  })
  token: string;

  @OneToOne(() => User)
  @JoinColumn()
  user: User;
}

我需要将模块 token 和用户 id 插入到 UserActive 中。 userActive.user = this; 行中的 this 是对象 user(当然有 id)。

当我插入新用户时,TypeORM 返回错误:

Key (userId)=(438dc281-3f03-45b0-bee8-76aecc894d14) is not present in table "user".

当然当我改成:

userActive.user = '438dc281-3f03-45b0-bee8-76aecc894d14'

然后一切正常。

我正在使用 Next.js

编辑:

我使用以下方式插入新用户:

const connection = getConnection().manager;

const user = new User();
user.name = name;
user.email = email;
user.password = await bcrypt.hash(password, 10);
await connection.save(user);

然后我将方法 handleAfterInsert 更改为:

@Entity()
export class User extends BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;
  
   //...

  @OneToOne(() => UserActive)
  userActive: UserActive;

  @AfterInsert()
  public async handleAfterInsert() {
    const userActive = new UserActive();
    userActive.token = randomString();
    userActive.user = this;
    await getConnection().manager.save(userActive);
  }
}

但 Nest 返回与之前相同的错误。

编辑 2:

我发现了这个问题:Retrieving ID in @AfterInsert operation

然后我尝试将我的方法 afterInsert 更改为:

@EventSubscriber()
export class UserSubscriber
  implements EntitySubscriberInterface<User> {
  listenTo() {
    return User;
  }

  async afterInsert(event: InsertEvent<User>) {
    const userActive = new UserActive();
    userActive.token = randomString();
    userActive.user = event.entity;
    await getConnection().getRepository(UserActive).save(userActive);
  }
}

但是现在没有向表 user active 添加任何内容,只向表 user 添加了新用户。

最佳答案

我怀疑这是因为 save(user) 和 save(userActive) 是在单独的数据库事务中完成的,所以在执行 save(userActive) 时用户还没有被提交到数据库——即使它有它的id 已生成,但尚未提交——因此 save(UserActive) 事务无法看到新用户,因此您会看到错误“Key (userId=xxx) is not present in table user”。

您也许可以解决此问题,但使用 entity manager而不是 repository .您不能使用存储库,因为它仅限于单个实体,但您在这里处理 2 个实体(用户和 userActive)。

更改您的 2 个保存以使用相同的实体管理器,如下所示:

保存用户:

const connection: Connection = await createConnection();
const manager = connection.manager;
var user = new User();
user.Name = "John";
// etc
// N.B. Use entity manager, not repository, to save: 
await manager.save(user);

同样保存 userActive 记录:

@Entity()
export class User extends BaseEntity {
// ...
    @AfterInsert()
    public async handleAfterInsert() {
        const userActive = new UserActive();
        userActive.token = randomString();
        userActive.user = this;
        // N.B. Use entity manager, not repository, here: 
        await getConnection().manager.save(userActive);
    }

更新的答案

我在上面测试了我的答案,确实它不起作用 - 如果我启用 typeorm logging我可以看到有两个单独的事务。

我在同一个 post 中找到了答案如您所见:再往下说您必须启用“订阅者”连接选项 - 这一点都不明显。

我是这样做的:在项目的“subscriber”文件夹中创建“afteruser.ts”,并确保该文件夹包含在 ormconfig.json 的“subscribers”连接选项中:

{
  // ...
  "logging": true,
  "entities": [ "entity/*.js" ],
  "subscribers": [ "subscriber/*.js" ],
  // ...
}

我怀疑您更新的解决方案中的问题是这一行,因为这会创建一个新事务:

await getConnection().getRepository(UserActive).save(userActive);

您需要使用相同的“实体管理器”,如下所示:

await event.manager.getRepository(UserActive).save(userActive);

关于node.js - TypeORM AfterInsert() 无法在另一个表中添加 userId,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66215930/

相关文章:

javascript - 如何在 NodeJS 中展开对象数组?

typescript - 为什么在尝试建立关系时 joinColumns 未定义?

unit-testing - 如何在Typeorm中输入事务回调?

mysql - 如何在 typeorm 中建立 OneToMany 关系?

node.js - 无法使用 Mongoose 在 NodeJS 中使用 $or 查询

javascript - 使用casperjs下载资源图片文件

javascript - 如何正确地使预加载器成为页面

typescript - 类型错误 : null value in column violates not-null: allow null values ​in a fk

typescript - 类型缺少以下属性

node.js - Discord.js:按 ID 获取消息给出错误的输出