repository.save使用插入而不是更新

时间:2018-07-29 17:59:17

标签: typeorm

我正在使用TypeORM的存储库模式和一个简单的表,两列,estate_num作为主键,estateId与mysql。

如果主键记录不存在,则要插入的repository.save method is supposed,否则,请对其进行更新。

相反,出现以下错误:

query: SELECT `estate`.`estate_num` AS `estate_estate_num`, `estate`.`estateId` AS `estate_estateId` FROM `estate` `estate` WHERE (`estate`.`estate_num` = ?) -- PARAMETERS: ["0"]
query: START TRANSACTION
query: INSERT INTO `estate`(`estate_num`, `estateId`) VALUES (?, ?) -- PARAMETERS: ["0","caae4e67796e4ac000743f009210fcb0467fdf87d0fbbf6107359cf53f5b544b79eefdfdd78f95d50301f20a9c3212cd3970af22b722e59313813e8c5d2732d0"]
query failed: INSERT INTO `estate`(`estate_num`, `estateId`) VALUES (?, ?) -- PARAMETERS: ["0","caae4e67796e4ac000743f009210fcb0467fdf87d0fbbf6107359cf53f5b544b79eefdfdd78f95d50301f20a9c3212cd3970af22b722e59313813e8c5d2732d0"]
error: { Error: ER_DUP_ENTRY: Duplicate entry '0' for key 'PRIMARY'

我可以手动运行SELECT,这是我确定要插入还是更新的方式。它会返回与预期的estate_num相匹配的一行。

为此的实体模型是:

@Entity()
export class Estate {
  @PrimaryColumn({
    name: 'estate_num',
  })
  estateNum: number;

  @Column({
    name: 'estateId',
  })
  estateId: string;
}

注意:estate_num不是不是自动递增的,因此将始终提供密钥。我知道这很奇怪。

谢谢!

3 个答案:

答案 0 :(得分:1)

我有同样的问题。我做错了。

在我以多种方式执行此操作之前,但是使用了错误的方式。

首先,我是这样做的:

const user = User.create({ id: 1, username: "newName" })

user.save();

给我一​​个ID Duplicate Entry的错误


第二,我是这样做的:

const user = User.create({ id: 1, username: "newName" })

User.save(user);

相同错误,重复条目。


第三次我是这样的:

const user = User.findOneOrFaile(1);
const newUser = { ...user, ..req.body }
User.save(newUser);

相同的错误。


我刚刚得到了帮助,应该这样做。您需要获取实例并使用Object.assign()

将其合并
try {
      const user: User = await User.findOneOrFail(id);
      Object.assign(user, { ...req.body }); <---- SO ITS LIKE THIS
      await user.save();
      res.json({
        meta: {},
        payload: {
          ...req.body
        }
      });
    } catch (error) {
      logger.error(error);
      res.status(404).json({
        error
      });
    }

答案 1 :(得分:1)

从日志中很明显,您已将ID作为字符串-- PARAMETERS: ["0"]进行了传递,但是Estate实体estateNum的类型为number。将ID转换为数字,然后再传递给repository.save

答案 2 :(得分:-1)

我整理了以下ts文件以进行测试:

Assembly.GetExecutingAssembly().GetTypes().Select(t => t.Namespace).ToList();

它按预期方式工作(基于以下日志输出):

import 'reflect-metadata';
import { createConnection } from 'typeorm';
import { Estate } from './entity/Estate';

createConnection().then(async connection => {
    const estate = new Estate();
    estate.estateNum = 0;
    estate.estateId = 'alpha';

    await connection.getRepository(Estate).save(estate);

    estate.estateId = 'beta';

    await connection.getRepository(Estate).save(estate);
});

我确实注意到,如果您不等待保存结果,typeorm将尝试两次插入该行(因为第一次保存在第二次开始之前未完成)。

这可能是您的问题吗?

(请注意,在此示例中我使用了sqlite3)。