【问题标题】:Why updating onetomany field makes all other previous filed null in typeorm为什么更新一对多字段会使 typeorm 中的所有其他先前字段为空
【发布时间】:2021-06-25 04:58:48
【问题描述】:

src/models/userModel.ts

@Entity()
    export class User extends BaseEntity {
      @PrimaryColumn()
      id: string;
    
      @Column()
      name: string;
    
      @Column()
      phoneNumber: string;
    
      @OneToMany((type) => Token, (token) => token.user)
      tokens: Token[];
    }
    
    @Entity()
    export class Token extends BaseEntity {
      @PrimaryGeneratedColumn()
      no: number;
    
      @PrimaryColumn({ length: 900 })
      token: string;
    
      @ManyToOne((type) => User, (user) => user.tokens)
      user: User;
    }

src/index.ts

import "reflect-metadata";
import { createConnection } from "typeorm";
import { Token, User } from "./models/userModel";
createConnection().then(async (_) => {
  for (let i = 1; i <= 2; i++) {
    console.log("Loop number " + i + "\n");
    let user = new User();
    user.id = "test1";
    user.name = "Om";
    user.phoneNumber = "432423";
    let token = new Token();
    token.token = "grgrg3432edsd";
    user.tokens = [token];
    await token.save();
    await user.save();
    (await User.find({ relations: ["tokens"] })).forEach((e) => console.log(e));
  }
});

运行nodemon src/typeorm.ts后输出是,

Loop number 1

User {
  id: 'test1',
  name: 'Om',
  phoneNumber: '432423',
  tokens: [ Token { no: 1, token: 'grgrg3432edsd' } ]
}
Loop number 2

User {
  id: 'test1',
  name: 'Om',
  phoneNumber: '432423',
  tokens: [ Token { no: 2, token: 'grgrg3432edsd' } ]
}

看到在第二个循环中它只返回一个 Token 对象,而不是分配给该用户的所有令牌

我确实使用 mysql 查询进一步检查了该表:-

mysql> select * from token;
+----+---------------+--------+
| no | token         | userId |
+----+---------------+--------+
|  1 | grgrg3432edsd | NULL   |
|  2 | grgrg3432edsd | test1  |
+----+---------------+--------+
2 rows in set (0.00 sec)

您可以在第一行看到 userId 变为空,我们将不胜感激。

【问题讨论】:

    标签: mysql node.js database typescript typeorm


    【解决方案1】:

    当您重新创建具有相同 id 的用户时,就像您更新实体列一样,当您在这一行中看到 user.tokens = [token] 时,您就像提供了一个新的令牌数组,其中创建了唯一的最新令牌, 我建议你,创建一个令牌数组,例如:

        for (let i = 1; i <= 2; i++) {
        console.log("Loop number " + i + "\n");
        let user = new User();
        user.id = "test1";
        user.name = "Om";
        user.phoneNumber = "432423";
        let token = new Token();
        token.token = "grgrg3432edsd";
        user.tokens = user.tokens.push(token); // push the new token the list of user's token
        await token.save();
        await user.save();
        (await User.find({ relations: ["tokens"] })).forEach((e) => console.log(e));
      }
    });
    

    更新

    要解决您的问题,您可以使用令牌属性中的推送:

     user.tokens = user.tokens.push(token);
    

    【讨论】:

    • 其实你没看懂我这里的情况,不清楚,其实我想插入到那个用户的token表中,例如如果用户从其他设备登录,则生成新令牌,我想将其添加到令牌表而不使以前的令牌 userId 为空,/n 这里的循环只是为了演示两个设备尝试登录并因此添加令牌在数据库中
    • 我知道了,你只需要从 tokens 属性进行推送(答案已更新)
    • push 返回数组的长度 numberuser.tokens 是数组 Token[] ,对不起,我不明白你想在这里解释什么。
    • 推送功能用于向列表中添加新项目,所以正如我在回答 user.tokens.push(token); 中添加的那样,我们向 token [] 的数组添加了一个新标记,如您所说
    • 我在这里为您提供任何解释
    【解决方案2】:

    我认为必须添加 user.tokens = [previousToken, newToken]; 您之前为该用户拥有的所有令牌

    【讨论】:

    • 我也这么认为,但是没有什么简单的方法可以做到这些吗?
    【解决方案3】:

    你的代码应该是这样的

    createConnection().then(async (_) => {
    
          const tokens: Token[] = [];
          for (let i = 1; i <= 2; i++) {
        
            let token = new Token();
            token.token = "grgrg3432edsd";
            
            const newToken = await token.save(); //this should work if .save() returns the token saved in database
            tokens.push(newToken);
          }
          let user = new User();
          user.id = "test1";
          user.name = "Om";
          user.phoneNumber = "432423";
          user.tokens = tokens;
          await user.save();
          (await User.find({ relations: ["tokens"] })).forEach((e) => console.log(e));
        });
    

    【讨论】:

      【解决方案4】:

      这行得通:-

        let User_user = await User.findOne(user);
        user.tokens = User_user?.tokens ?? [];
        user.tokens.push(token);
        user.save();
      

      欢迎提出任何使此代码更简单的建议。 即使您有不同的方法,也请随时分享。

      【讨论】:

        猜你喜欢
        • 2022-09-23
        • 1970-01-01
        • 2019-02-22
        • 1970-01-01
        • 2021-08-12
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多