[英]Sequelize hasMany and belongsTo issue
I am going to create 2 tables in Mysql using node.js & sequelize.js.我将使用 node.js 和 sequelize.js 在 Mysql 中创建 2 个表。
I have 2 models - User
and Company
我有 2 个模型 -
User
和Company
User has following fields - id - username - password用户有以下字段 - id - 用户名 - 密码
Company has following fields - id - name - owner_id (This is foreign key of id in User, not primary key)公司有以下字段 - id - name - owner_id(这是 User 中 id 的外键,不是主键)
In User
model, I added the following code.在
User
模型中,我添加了以下代码。
User.hasMany(Company)
In Company
model, I added the following code.在
Company
模型中,我添加了以下代码。
Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });
Now, the problem is that in companies
table, I can see that there're 2 columns - owner_id
and User_id
.现在,问题是在
companies
表中,我可以看到有 2 列 - owner_id
和User_id
。
Is there any way not to add User_id
in sequelize option?有没有办法不在续集选项中添加
User_id
?
Short answer: you should add foreignKey
option for User.hasMany(Company)
association like this:简短回答:您应该为
User.hasMany(Company)
关联添加foreignKey
选项,如下所示:
User.hasMany(Company, { foreignKey: 'owner_id' });
Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });
Long answer, here is the completed working demo with some simple tests:答案很长,这是带有一些简单测试的完整工作演示:
index.ts
: index.ts
:
import { sequelize } from '../../db';
import { Model, DataTypes, HasManyGetAssociationsMixin, BelongsToGetAssociationMixin } from 'sequelize';
import assert from 'assert';
class User extends Model {
public id!: number;
public username!: string;
public password!: string;
public getCompanies!: HasManyGetAssociationsMixin<Company>;
}
User.init(
{
username: DataTypes.STRING,
password: DataTypes.STRING,
},
{ sequelize, modelName: 'User', underscored: true },
);
class Company extends Model {
public id!: number;
public name!: string;
public owner_id!: number;
public getOwner!: BelongsToGetAssociationMixin<User>;
}
Company.init({ name: DataTypes.STRING }, { sequelize, modelName: 'Company', underscored: true });
User.hasMany(Company, { foreignKey: 'owner_id' });
Company.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });
(async function test() {
try {
await sequelize.sync({ force: true });
// seed
await User.create(
{ username: 'jenifer', password: '123', Companies: [{ name: 'Google' }, { name: 'Twitter' }] },
{ include: [Company] },
);
// assertion testing
const user: User = await User.findByPk(1);
assert(user.username === 'jenifer', 'The user should be jenifer');
const companies: Company[] = await user.getCompanies();
assert(companies.length === 2, 'The count of companies of jenifer should be 2');
const company1 = companies[0];
assert(typeof company1['User_id'] === 'undefined', 'User_id column should not be added to company model');
const owner = await company1.getOwner();
assert(owner.username === user.username);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
Data records in database:数据库中的数据记录:
node-sequelize-examples=# select * from "User";
id | username | password
----+----------+----------
1 | jenifer | 123
(1 row)
node-sequelize-examples=# select * from "Company";
id | name | owner_id
----+---------+----------
1 | Google | 1
2 | Twitter | 1
(2 rows)
The execution results of the above code without assertion failure:上面代码没有断言失败的执行结果:
{ POSTGRES_HOST: '127.0.0.1',
POSTGRES_PORT: '5430',
POSTGRES_PASSWORD: 'testpass',
POSTGRES_USER: 'testuser',
POSTGRES_DB: 'node-sequelize-examples' }
Executing (default): DROP TABLE IF EXISTS "Company" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): DROP TABLE IF EXISTS "User" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "User" ("id" SERIAL , "username" VARCHAR(255), "password" VARCHAR(255), PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'User' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "Company" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "Company" ("id" SERIAL , "name" VARCHAR(255), "owner_id" INTEGER REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'Company' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "User" ("id","username","password") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "Company" ("id","name","owner_id") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "Company" ("id","name","owner_id") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): SELECT "id", "username", "password" FROM "User" AS "User" WHERE "User"."id" = 1;
Executing (default): SELECT "id", "name", "owner_id" FROM "Company" AS "Company" WHERE "Company"."owner_id" = 1;
Executing (default): SELECT "id", "username", "password" FROM "User" AS "User" WHERE "User"."id" = 1;
sequelize version:续集版本:
"sequelize": "^5.21.3",
Source code: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60190182源代码: https : //github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/60190182
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.