在 typeORM 中的 @ManyToMany 中保存关系会覆盖先前的条目
Posted
技术标签:
【中文标题】在 typeORM 中的 @ManyToMany 中保存关系会覆盖先前的条目【英文标题】:Save relation in @ManyToMany in typeORM overwrites previous entry 【发布时间】:2021-07-19 06:23:37 【问题描述】:我用typeorm/mysql
和nodejs/express
做了一个追随者系统。
保存逻辑:
router.post("/subscriptions", async (req, res) =>
const currentUserId = Number(req.headers.userid);
const userToFollowId = req.body.userToFollowId;
const userRepository = getRepository(User);
try
let user;
let userToFollow;
user = await userRepository.findOneOrFail(currentUserId);
userToFollow = await userRepository.findOneOrFail(userToFollowId);
if (user && userToFollow)
user.followers = [...(user?.followers || []), userToFollow];
await userRepository.save(user);
res.status(201).send("Followed");
catch (e)
console.log(e);
);
@User
具有自引用关系的实体:
@Entity()
export class User
@PrimaryGeneratedColumn()
id!: number;
@Column( nullable: true )
name!: string;
@Column()
email!: string;
@Column()
password!: string;
@OneToMany(() => Post, (post) => post.user)
posts!: Post[];
@OneToMany(() => Comment, (comment) => comment.user)
comments!: Comment[];
@ManyToMany(() => User, (user) => user.following, cascade: true )
@JoinTable()
followers!: User[];
@ManyToMany(() => User, (user) => user.followers)
following!: User[];
@Column(
default: () => "NOW()",
)
createdAt!: Date;
@Column(
default: () => "NOW()",
)
@UpdateDateColumn()
updatedAt!: Date;
假设curentUserId
为5,userToFollow
ID 为6。它将成功保存到数据库中。当我尝试通过使用相同的 currentUserId
of 5 和 userToFollow
一些其他 ID(例如 7)来保存另一个条目时会出现问题,在这种情况下是数据库中的前一个条目:
用户 5
关注 ID 为 6
的用户将是 overwritten
到:
用户5
关注ID为7
的用户
这是我第一次保存时的查询:
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?) -- PARAMETERS: [5]
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?) -- PARAMETERS: ["6"]
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?, ?) -- PARAMETERS: [5,6]
query: SELECT `User_followers_rid`.`userId_1` AS `userId_1`, `User_followers_rid`.`userId_2` AS `userId_2` FROM `user` `user` INNER JOIN `user_followers_user` `User_followers_rid` ON (`User_followers_rid`.`userId_1` = ? AND `User_followers_rid`.`userId_2` = `user`.`id`) OR (`User_followers_rid`.`userId_1` = ? AND `User_followers_rid`.`userId_2` = `user`.`id`) ORDER BY `User_followers_rid`.`userId_2` ASC, `User_followers_rid`.`userId_1` ASC -- PARAMETERS: [5,6]
query: START TRANSACTION
query: INSERT INTO `user_followers_user`(`userId_1`, `userId_2`) VALUES (?, ?) -- PARAMETERS: [5,6]
query: COMMIT
这是我认为出现问题的第二个问题(请注意DELETE
部分):
query: START TRANSACTION
query: INSERT INTO `user_followers_user`(`userId_1`, `userId_2`) VALUES (?, ?) -- PARAMETERS: [5,6]
query: COMMIT
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?) -- PARAMETERS: [5]
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?) -- PARAMETERS: ["7"]
query: SELECT `User`.`id` AS `User_id`, `User`.`name` AS `User_name`, `User`.`email` AS `User_email`, `User`.`password` AS `User_password`, `User`.`createdAt` AS `User_createdAt`, `User`.`updatedAt` AS `User_updatedAt` FROM `user` `User` WHERE `User`.`id` IN (?, ?) -- PARAMETERS: [5,7]
query: SELECT `User_followers_rid`.`userId_1` AS `userId_1`, `User_followers_rid`.`userId_2` AS `userId_2` FROM `user` `user` INNER JOIN `user_followers_user` `User_followers_rid` ON (`User_followers_rid`.`userId_1` = ? AND `User_followers_rid`.`userId_2` = `user`.`id`) OR (`User_followers_rid`.`userId_1` = ? AND `User_followers_rid`.`userId_2` = `user`.`id`) ORDER BY `User_followers_rid`.`userId_2` ASC, `User_followers_rid`.`userId_1` ASC -- PARAMETERS: [5,7]
query: START TRANSACTION
query: INSERT INTO `user_followers_user`(`userId_1`, `userId_2`) VALUES (?, ?) -- PARAMETERS: [5,7]
query: DELETE FROM `user_followers_user` WHERE `userId_1` = ? AND `userId_2` = ? -- PARAMETERS: [5,6]
query: COMMIT
【问题讨论】:
【参考方案1】:你有这个问题的原因是当你查询用户时,你没有添加 followers
与它的关系。写一个console.log(user)
,你会看到user
对象没有followers
属性。这就是为什么每次调用 api 时,它都会用新的替换旧的。
您必须在查询中添加followers
关系。这将以user.followers
的User
对象的形式返回所有现有的关注者列表。您可以使用的另一件事
user.followers.push(userToFollow);
而不是 user.followers = [...(user?.followers || []), userToFollow];
在您的代码中。使用下面的代码,
try
let user = await userRepository.findOneOrFail(currentUserId, relations: ["followers"] );
let userToFollow = await userRepository.findOneOrFail(userToFollowId);
if (user && userToFollow)
user.followers.push(userToFollow);
await userRepository.save(user);
return res.status(201).send("Followed");
else
throw new Error("User not found!")
catch (e)
console.log(e);
【讨论】:
非常感谢!它就像一个魅力 :) 我想知道为什么当我尝试在 follower 属性上使用 .push 方法时会出现未定义的错误,但现在这也很有意义!以上是关于在 typeORM 中的 @ManyToMany 中保存关系会覆盖先前的条目的主要内容,如果未能解决你的问题,请参考以下文章
NestJS + TypeORM 中的 JoinTable 问题