Ошибка означает наличие циклических ссылок между вашими модулями. Вы должны поместить модели в модуль, подобный index.ts
, и установить ассоциации здесь. Обратите внимание на мою структуру каталогов файлов:
Например,
./models/book.ts
:
import Sequelize from 'sequelize';
import { sequelize } from '../../../db';
export default class Book extends Sequelize.Model {}
Book.init(
{
title: {
allowNull: false,
type: Sequelize.STRING(100),
},
},
{ sequelize, modelName: 'books' },
);
./models/author.ts
:
import Sequelize from 'sequelize';
import { sequelize } from '../../../db';
export default class Author extends Sequelize.Model {}
Author.init(
{
firstName: {
allowNull: false,
type: Sequelize.STRING(100),
},
lastName: {
allowNull: false,
type: Sequelize.STRING(100),
},
},
{ sequelize, modelName: 'authors' },
);
./models/authorbook.ts
:
import Sequelize from 'sequelize';
import { sequelize } from '../../../db';
export default class AuthorBook extends Sequelize.Model {}
AuthorBook.init(
{
authorId: {
type: Sequelize.INTEGER,
allowNull: false,
},
bookId: {
type: Sequelize.INTEGER,
allowNull: false,
},
},
{ sequelize, modelName: 'authorbooks' },
);
./models/index.ts
:
import Author from './author';
import Book from './book';
import AuthorBook from './authorbook';
Author.hasMany(AuthorBook, {
onUpdate: 'CASCADE',
});
Book.hasMany(AuthorBook, {
onUpdate: 'CASCADE',
});
AuthorBook.belongsTo(Author, { foreignKey: 'authorId' });
AuthorBook.belongsTo(Book, { foreignKey: 'bookId' });
export { Author, Book, AuthorBook };
Теперь мы можем использовать эти модели.
index.ts
:
import { Author, AuthorBook, Book } from './models';
import { sequelize } from '../../db';
import faker from 'faker';
(async function test() {
try {
await sequelize.sync({ force: true });
// seed
const author = await Author.create({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
});
const book = await Book.create({
title: faker.lorem.words(3),
});
await AuthorBook.create({ authorId: author.id, bookId: book.id });
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
Результаты выполнения:
Executing (default): DROP TABLE IF EXISTS "authorbooks" CASCADE;
Executing (default): DROP TABLE IF EXISTS "books" CASCADE;
Executing (default): DROP TABLE IF EXISTS "authors" CASCADE;
Executing (default): DROP TABLE IF EXISTS "authors" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "authors" ("id" SERIAL , "firstName" VARCHAR(100) NOT NULL, "lastName" VARCHAR(100) NOT NULL, 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 = 'authors' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "books" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "books" ("id" SERIAL , "title" VARCHAR(100) NOT NULL, 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 = 'books' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): DROP TABLE IF EXISTS "authorbooks" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "authorbooks" ("id" SERIAL , "authorId" INTEGER NOT NULL REFERENCES "authors" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "bookId" INTEGER NOT NULL REFERENCES "books" ("id") ON DELETE CASCADE 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 = 'authorbooks' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "authors" ("id","firstName","lastName") VALUES (DEFAULT,$1,$2) RETURNING *;
Executing (default): INSERT INTO "books" ("id","title") VALUES (DEFAULT,$1) RETURNING *;
Executing (default): INSERT INTO "authorbooks" ("id","authorId","bookId") VALUES (DEFAULT,$1,$2) RETURNING *;
проверка базы данных:
node-sequelize-examples=# select * from "authors";
id | firstName | lastName
----+-----------+----------
1 | Laron | Deckow
(1 row)
node-sequelize-examples=# select * from "books";
id | title
----+-------------------------
1 | facilis molestias sequi
(1 row)
node-sequelize-examples=# select * from "authorbooks";
id | authorId | bookId
----+----------+--------
1 | 1 | 1
(1 row)
Версии зависимостей: "sequelize": "^5.21.3"
, postgres:9.6
исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/61163520