尝试将行插入表因为带有sequelize.js的UUID外键时出错

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试将行插入表因为带有sequelize.js的UUID外键时出错相关的知识,希望对你有一定的参考价值。

我正在使用sequelize.js与node.js和postgres。我从一个例子中得到了2个简单的表作为'POC'。我将ID更改为UUID,我在插入第二个表(使用UUID FK)时出现问题。

我正在使用邮递员来测试它。我用UUID创建todo行没有问题,然后我试图创建一个todo项目,其中有一个todo id作为外键,似乎它无法识别该ID!

我在postgres中尝试了一个手动脚本并且它有效。我可能错过了一些明智的代码,但我无法弄清楚是什么。

这是邮递员回复给我的错误 -

{
    "name": "SequelizeDatabaseError",
    "parent": {
        "name": "error",
        "length": 96,
        "severity": "ERROR",
        "code": "22P02",
        "file": "uuid.c",
        "line": "137",
        "routine": "string_to_uuid",
        "sql": "INSERT INTO "TodoItems" ("id","content","complete","createdAt","updatedAt","todoId") VALUES ($1,$2,$3,$4,$5,$6) RETURNING *;"
    },
    "original": {
        "name": "error",
        "length": 96,
        "severity": "ERROR",
        "code": "22P02",
        "file": "uuid.c",
        "line": "137",
        "routine": "string_to_uuid",
        "sql": "INSERT INTO "TodoItems" ("id","content","complete","createdAt","updatedAt","todoId") VALUES ($1,$2,$3,$4,$5,$6) RETURNING *;"
    },
    "sql": "INSERT INTO "TodoItems" ("id","content","complete","createdAt","updatedAt","todoId") VALUES ($1,$2,$3,$4,$5,$6) RETURNING *;"
}

以下是相关的js文件 -

todoItems.js控制器 -

const TodoItem = require('../dal/models').TodoItem;
const uuid = require('uuid/v4');

module.exports = {
  create(req, res) {
    return TodoItem
      .create({
        content: req.body.content,
        todoId: req.params.todoId,
      })
      .then(todoItem => res.status(201).send(todoItem))
      .catch(error => res.status(400).send(error));
  },

  update(req, res) {
    return TodoItem
      .find({
        where: {
          id: req.params.todoItemId,
          todoId: req.params.todoId,
        },
      })
      .then(todoItem => {
        if (!todoItem) {
          return res.status(404).send({
            message: 'TodoItem Not Found',
          });
        }

        return todoItem
          .update({
            content: req.body.content || todoItem.content,
            complete: req.body.complete || todoItem.complete,
          })
          .then(updatedTodoItem => res.status(200).send(updatedTodoItem))
          .catch(error => res.status(400).send(error));
      })
      .catch(error => res.status(400).send(error));
  },

  destroy(req, res) {
    return TodoItem
      .find({
        where: {
          id: req.params.todoItemId,
          todoId: req.params.todoId,
        },
      })
      .then(todoItem => {
        if (!todoItem) {
          return res.status(404).send({
            message: 'TodoItem Not Found',
          });
        }

        return todoItem
          .destroy()
          .then(() => res.status(204).send())
          .catch(error => res.status(400).send(error));
      })
      .catch(error => res.status(400).send(error));
  },
};

todos.js控制器 -

const Todo = require('../dal/models').Todo;
const TodoItem = require('../dal/models').TodoItem;

module.exports = {
  create(req, res) {
    return Todo
      .create({
        title: req.body.title,
      })
      .then((todo) => res.status(201).send(todo))
      .catch((error) => res.status(400).send(error));
  },

  list(req, res) {
    return Todo
      .findAll({
        include: [{
          model: TodoItem,
          as: 'todoItems',
        }],
        order: [
          ['createdAt', 'DESC'],
          [{ model: TodoItem, as: 'todoItems' }, 'createdAt', 'ASC'],
        ],
      })
      .then((todos) => res.status(200).send(todos))
      .catch((error) => res.status(400).send(error));
  },

  retrieve(req, res) {
    return Todo
      .findByPk(req.params.todoId, {
        include: [{
          model: TodoItem,
          as: 'todoItems',
        }],
      })
      .then((todo) => {
        if (!todo) {
          return res.status(404).send({
            message: 'Todo Not Found',
          });
        }
        return res.status(200).send(todo);
      })
      .catch((error) => res.status(400).send(error));
  },

  update(req, res) {
    return Todo
      .findByPk(req.params.todoId, {
        include: [{
          model: TodoItem,
          as: 'todoItems',
        }],
      })
      .then(todo => {
        if (!todo) {
          return res.status(404).send({
            message: 'Todo Not Found',
          });
        }
        return todo
          .update({
            title: req.body.title || todo.title,
          })
          .then(() => res.status(200).send(todo))
          .catch((error) => res.status(400).send(error));
      })
      .catch((error) => res.status(400).send(error));
  },

  destroy(req, res) {
    return Todo
      .findByPk(req.params.todoId)
      .then(todo => {
        if (!todo) {
          return res.status(400).send({
            message: 'Todo Not Found',
          });
        }
        return todo
          .destroy()
          .then(() => res.status(204).send())
          .catch((error) => res.status(400).send(error));
      })
      .catch((error) => res.status(400).send(error));
  },
};

todo表创建迁移 -

module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.createTable('Todos', {
      id: {
        allowNull: false,
        primaryKey: true,
        type: Sequelize.UUID,
      },
      title: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    }),
  down: (queryInterface /* , Sequelize */) => queryInterface.dropTable('Todos'),
};

todo-item表创建迁移 -

module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.createTable('TodoItems', {
      id: {
        allowNull: false,
        primaryKey: true,
        type: Sequelize.UUID,
      },
      content: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      complete: {
        type: Sequelize.BOOLEAN,
        defaultValue: false,
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      todoId: {
        type: Sequelize.UUID,
        onDelete: 'CASCADE',
        references: {
          model: 'Todos',
          key: 'id',
          as: 'todoId',
        },
      },
    }),
  down: (queryInterface /* , Sequelize */) =>
    queryInterface.dropTable('TodoItems'),
};

所有型号 -

const uuid = require('uuid/v4');

'use strict';

module.exports = (sequelize, DataTypes) => {
  const Todo = sequelize.define('Todo', {
    title: {
      type: DataTypes.STRING,
      allowNull: false,
    }
  });
  Todo.associate = (models) => {
    Todo.hasMany(models.TodoItem, {
      foreignKey: 'todoId',
      as: 'todoItems',
    });
  };
  Todo.beforeCreate((item, _ ) => {
    return item.id = uuid();
  });
  return Todo;
};

todo-item模型 -

const uuid = require('uuid/v4');

'use strict';

module.exports = (sequelize, DataTypes) => {
  const TodoItem = sequelize.define('TodoItem', {
    content: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    complete: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
    }
  });
  TodoItem.associate = (models) => {
    TodoItem.belongsTo(models.Todo, {
      foreignKey: 'todoId',
      onDelete: 'CASCADE',
    });
  };
  TodoItem.beforeCreate((item, _ ) => {
    return item.id = uuid();
  });
  return TodoItem;
};
答案

你的路由器代码是什么样的?您是否正在使用todoId的正确路径参数?如果您使用快递,例如。它看起来应该像app.post("/todos/:todoId/todo_items", todoItemController.create)。请注意camelcase todoId。这将确保您在todoItems控制器中引用的req.params.todoId具有正确的值。

此外,请确保您有正确的正文解析器来正确处理req.body.content。在express中,这将通过body body-parser library和app.use(bodyParser.json())完成。在todoItem控制器创建代码中添加断点或日志语句,并验证您确实具有正确的参数值。

以上是关于尝试将行插入表因为带有sequelize.js的UUID外键时出错的主要内容,如果未能解决你的问题,请参考以下文章

将行从一个链接表插入到另一个链接表

尝试使用触发器以将行插入另一个表时出现语法错误

我们可以在使用 sequelize js 节点在 mysql 表中插入数据后给时间吗

Node.js / Sequelize.js / Express.js - 如何插入多对多关联? (同步/异步?)

带有 pg8000 的 PostgreSQL - 从 SQL 插入结果到另一个表

Spring JDBC:即使将行插入表中,也不返回自动生成的ID