node.js - TypeORM AfterInsert() 无法在另一个表中添加 userId
问题描述
我有一个用户实体:
@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
. this
in lineuserActive.user = this;
是对象user
(当然是id
)。
当我插入新用户时,TypeORM 返回错误:
表“用户”中不存在键 (userId)=(438dc281-3f03-45b0-bee8-76aecc894d14)。
当然,当我更改为:
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 日志记录,我可以看到有两个单独的事务。
我在与您相同的帖子中找到了答案:进一步说您必须启用“订阅者”连接选项 - 这一点都不明显。
我是这样做的:在项目的“订阅者”文件夹中创建“afteruser.ts”,并确保该文件夹包含在 ormconfig.json 中的“订阅者”连接选项中:
{
// ...
"logging": true,
"entities": [ "entity/*.js" ],
"subscribers": [ "subscriber/*.js" ],
// ...
}
我怀疑您更新的解决方案中的问题是这一行,因为这会创建一个新事务:
await getConnection().getRepository(UserActive).save(userActive);
您需要使用相同的“实体管理器”,如下所示:
await event.manager.getRepository(UserActive).save(userActive);
推荐阅读
- c# - 将 Excel/Word/PDF 合并导出为 PDF
- python - 使用 ffmpeg 在 python 中连接 mp3
- c++ - win32 c++ 将窗口位置设置为右下角
- excel - 如何使用 selenium webdriver 和 VBA 选择没有 id 的单选按钮
- html - HTML/express 中的页面转换
- python-3.x - OneVsRest predict_proba() 和 predict() 不匹配?
- javascript - 将 Js 变量传递到数据表列
- r - 如何获取列表列中包含元素的行
- python - 如何从图像中找到 Python 中的字体大小?
- android - 如何在类上使用 Kotlin 扩展函数?