我使用 sequelize ORM。我创建了一个注册路由和控制器来创建新用户。我用AVA测试创建了一个新用户,但是自增功能不能正常使用。尽管是创建的第四个用户,这个使用 AVA 测试创建的新用户的 ID 为 1(其他三个用户是使用 Sequelize seeders 创建的)。我检查了数据库架构并确认“id”字段设置为自动递增。关于如何解决这个问题的任何想法?
终端输出:
npm test .../tests/register/registerTest.js
> test
> ava --require dotenv/...tests/register/registerTest.js
Executing (default): INSERT INTO "Users" ("uuid","username","email","password","createdAt","updatedAt") VALUES ($1,$2,$3,$4,$5,$6) RETURNING "uuid","username","email","password","createdAt","updatedAt";
✔ RegisterNewUser function should create a new user and return a token (127ms)
ℹ {
token: 'eyJhbGciOiJIUzI1N...Z_iVY8hjgsf9Ak',
user: {
createdAt: '2023-03-07T07:48:53.393Z',
email: '[email protected]',
password: '$2b$10$kNeC1h7d0wX7WPQC3H.94OlpXveXVeaP7WaWEIGQN6VLypSVKoAE.',
updatedAt: '2023-03-07T07:48:53.393Z',
username: 'testuser',
uuid: 'e33c6803-1c18-4d25-906f-2d6de8726d27',
},
}
─
1 test passed
PSQL终端输出:
database_test=# SELECT * FROM "Users";
id | uuid | username | email | password | createdAt | updatedAt
----+--------------------------------------+----------+----------------------+--------------------------------------------------------------+----------------------------+----------------------------
1 | 15bf1cb7-8346-4140-8b36-ced76facb4d7 | johndoe | [email protected] | $2b$10$1r.N1fS6ea82w9WgMZmdsevl/awhaWjSfWgwHzMXSWDNPdZlfS.bS | 2023-03-07 07:45:28.403+00 | 2023-03-07 07:45:28.403+00
2 | af947f46-2991-43fd-aaec-dec95c40a729 | janedoe | [email protected] | $2b$10$8H7ktluUZrr21SzE7Eo2MuegtmaCLMWjxHnQvg8LrlAD1uLI1BICm | 2023-03-07 07:45:28.412+00 | 2023-03-07 07:45:28.412+00
3 | d2658a11-b088-4e86-a351-ee628c3a7cad | billdoe | [email protected] | $2b$10$CBWz3iUSVot3nLqgSP3z4.ma2tiCp8SaPTKPRC3Z8fjHNMDJs.oIO | 2023-03-07 07:45:28.405+00 | 2023-03-07 07:45:28.405+00
1 | e33c6803-1c18-4d25-906f-2d6de8726d27 | testuser | [email protected] | $2b$10$kNeC1h7d0wX7WPQC3H.94OlpXveXVeaP7WaWEIGQN6VLypSVKoAE. | 2023-03-07 07:48:53.393+00 | 2023-03-07 07:48:53.393+00
\d "Users"
database_test=# \d "Users"
Table "public.Users"
Column | Type | Collation | Nullable | Default
-----------+--------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('"Users_id_seq"'::regclass)
uuid | uuid | | not null |
username | character varying(255) | | not null |
email | character varying(255) | | not null |
password | character varying(255) | | not null |
createdAt | timestamp with time zone | | not null |
updatedAt | timestamp with time zone | | not null |
模型/user.js
'use strict';
// Import the bcrypt library for password hashing
const {
Model
} = require('sequelize');
// Import the bcrypt library for password hashing
const bcrypt = require('bcrypt');
// Define a sequelize model for a User
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
...
})
}
}
User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
unique: true,
primaryKey: true,
},
...
}, {
sequelize,
modelName: 'User',
// Add hooks to run code before or after certain events
hooks: {
// Hash the user's password before creating a new user
beforeCreate: (User) => {
const salt = bcrypt.genSaltSync(10);
User.password = bcrypt.hashSync(User.password, salt);
}
},
});
return User;
};
迁移/20230223064615-create-user.js
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
type: Sequelize.INTEGER,
onDelete: 'CASCADE'
},
...
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Users');
}
};
播种机:
module.exports = {
// The up function is responsible for defining the changes that should be applied to the database schema.
up: async (queryInterface, Sequelize) => {
// Define an array of user objects with plaintext passwords.
const users = [{
id: 1,
uuid: uuidv4(),
username: 'johndoe',
email: '[email protected]',
password: 'password123'
},
{
id: 2,
uuid: uuidv4(),
username: 'janedoe',
email: '[email protected]',
password: 'password456'
},
....
// The down function is responsible for undoing the changes made to the database schema by the up function.
down: async (queryInterface, Sequelize) => {
// Delete all users from the Users table using the bulkDelete function provided by Sequelize.
return queryInterface.bulkDelete('Users', null, {});
}
};
我已经在我的播种器代码中为用户手动定义了
id
字段。但是,如果我在数据库中使用自动递增 ID,则不应手动为每条记录定义 ID。
当我将一条新记录插入到具有自动递增 ID 列的表中时,数据库将自动为该记录分配下一个可用 ID。通过在我的播种器代码中手动定义 ID,我将覆盖此行为并导致潜在的问题。
为了解决这个问题,我从我的播种器代码中删除了id
字段,允许数据库自动分配ID。通过此更改,数据库在插入每个用户记录时为其分配一个唯一 ID,确保 ID 是唯一且按顺序排列的。