I am trying to add associations to my defined tables and i am not sure if i have done it correctly. Basically i have a MySQL database that i want to re-create in sequelize as a second database.
MySQL tables:
CREATE TABLE IF NOT EXISTS account(
accountId INTEGER PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password CHAR(60) NOT NULL,
CONSTRAINT usernameUnique UNIQUE (username)
);
CREATE TABLE IF NOT EXISTS thread(
threadId INTEGER PRIMARY KEY AUTO_INCREMENT,
threadName VARCHAR(50) NOT NULL,
threadOfAccount INTEGER NULL,
FOREIGN KEY (threadOfAccount) REFERENCES account(accountId),
CONSTRAINT threadNameUnique UNIQUE (threadName)
);
CREATE TABLE IF NOT EXISTS post(
postId INTEGER PRIMARY KEY AUTO_INCREMENT,
postTitle VARCHAR(50) NOT NULL,
postContent TEXT NOT NULL,
postOnThread INTEGER NOT NULL,
postOfAccount INTEGER NOT NULL,
FOREIGN KEY (postOnThread) REFERENCES thread(threadId),
FOREIGN KEY (postOfAccount) REFERENCES account(accountId),
CONSTRAINT postTitleUnique UNIQUE (postTitle)
);
I have defined the tables identically in sequelize.
The associations added for the moment:
db.thread.associate = (models) => {
this.thread.belongsTo(models.account, {
foreignKey: 'threadOfAccount'
})
}
db.thread.associate = (models) => {
this.thread.hasMany(models.post)
}
db.post.associate = (models) => {
this.post.belongsTo(models.thread, {
foreignKey: 'postOnThread'
})
}
db.post.associate = (models) => {
this.post.belongsTo(models.account, {
foreignKey: 'postOfAccount'
})
}
When i make a db call conatining a LEFT JOIN using sequelize like below:
module.exports = function({ SQLiteDb }){
return {
getAllPosts: function(threadId, callback) {
SQLiteDb.post.findAll({
include:[{
model: SQLiteDb.thread, as: 'thread',
where: { postOnThread: threadId },
required: false,
}],
raw: true
})
.then(posts => callback([], posts))
.catch(error => console.log(error, " ERRPR")
}
}
}
I receive this error:
EagerLoadingError [SequelizeEagerLoadingError]: thread is not associated to post!
post.belongsTo(models.thread, {
foreignKey: 'postOnThread',
as: 'thread',
});
post.belongsTo(models.account, {
foreignKey: 'postOfAccount',
as: 'account',
});
thread.belongsTo(models.account, {
foreignKey: 'threadOfAccount',
as: 'account',
});
thread.hasMany(models.post, {
foreignKey: 'postOnThread',
as: 'posts',
});
Test
const posts = await db.post.findAll({ include: ['account', 'thread'] });
console.log(JSON.parse(JSON.stringify(posts)));
const threads = await db.thread.findAll({ include: ['account', 'posts'] });
console.log(JSON.parse(JSON.stringify(threads)));
const accounts = await db.account.findAll({ include: ['account', 'posts'] });
console.log(JSON.parse(JSON.stringify(accounts)));
We need call after associate definition
db.account.associate(db);
db.post.associate(db);
db.thread.associate(db);
Related
I am trying to establish One-to-many relation using sequelize, MySQL and Node-Express I am getting the following error.
server is running on port : 8080
Executing (default): SELECT 1+1 AS result
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'products' AND TABLE_SCHEMA = 'node_sequelize_api_db'
connected to db
Executing (default): CREATE TABLE IF NOT EXISTS `products` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255) NOT NULL, `price` INTEGER, `description` TEXT, `published` TINYINT(1), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `products`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'reviews' AND TABLE_SCHEMA = 'node_sequelize_api_db'
Executing (default): CREATE TABLE IF NOT EXISTS `reviews` (`id` INTEGER NOT NULL auto_increment , `rating` INTEGER, `description` TEXT, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `productId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`productId`) REFERENCES `products` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB;
(node:15924) UnhandledPromiseRejectionWarning: Error
at Query.run (/home/grace/Desktop/_SOFTWARE_ENGINEER/FULLSTACK/node_sequelize/node_modules/sequelize/lib/dialects/mysql/query.js:52:25)
at retry (/home/grace/Desktop/_SOFTWARE_ENGINEER/FULLSTACK/node_sequelize/node_modules/sequelize/lib/sequelize.js:314:28)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:15924) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:15924) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
THIS IS MY Model/index.js where the relation happens
require('dotenv').config();
const {Sequelize, DataTypes} = require('sequelize')
const sequelize = new Sequelize(
process.env.DB,
process.env.USER,
process.env.PASSWORD,{
host:process.env.HOST,
dialect: process.env.DIALECT,
operatorsAlias: false,
/*pool:{
max: dbConfig.pool.max,
min: dbConfig.pool.min,
acquire: dbConfig.pool.acquire,
idle: dbConfig.pool.idle
}*/
}
)
sequelize.authenticate()
.then(() =>{
console.log('connected to db')
})
.catch(err =>{
console.log('Error' + err)
})
const db = {}
db.Sequelize = Sequelize
db.sequelize = sequelize
db.products = require('./productModel.js')(sequelize, DataTypes);
db.reviews = require('./reviewModel.js')(sequelize, DataTypes);
//it won't create the table over and over
db.sequelize.sync({force: false})
.then(()=>{
console.log('yes re-sync done!')
})
//implement One-to-Many relationship
db.products.hasMany(db.reviews,{
foreignKey: 'product_id',
as: 'review',
})
db.reviews.belongsTo(db.products,{
foreignKey: 'product_id',
as: 'product'
})
Model/productModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define("product", {
title: {
type: DataTypes.STRING,
allowNull: false
},
price: {
type: DataTypes.INTEGER
},
description: {
type: DataTypes.TEXT
},
published: {
type: DataTypes.BOOLEAN
}
})
}
Review Model
module.exports = (sequelize, DataTypes) => {
return sequelize.define("review", {
rating: {
type: DataTypes.INTEGER,
},
description: {
type: DataTypes.TEXT
}
})
}
Product controller
//7. connect 1 to many relation Roduct to Review
const getProductReviews = async (req, res) =>{
try{
const data = await Product.findAll({include: Review})
}catch(e){
console.error(e)
}
}
module.exports ={
addProduct,
getAllProducts,
getOneProduct,
updateProduct,
deleteProduct,
getPublishedProduct,
getProductReviews
}
If I remove the following code from Model/index.js
//implement One-to-Many relationship
db.products.hasMany(db.reviews,{
foreignKey: 'product_id',
as: 'review',
})
db.reviews.belongsTo(db.products,{
foreignKey: 'product_id',
as: 'product'
})
Everything runs smoothly, so I am convinced that the error comes from the relationship I am trying to implement, I went through the documentation try to implement it differently but I am still getting the same error.
In your code you call sync(..) method which returns Promise. And looks like this promise is rejected. So try to replace
db.sequelize.sync({force: false})
.then(()=>{
console.log('yes re-sync done!')
})
with something like
db.sequelize.sync({force: false})
.then(()=>{
console.log('yes re-sync done!')
})
.catch(e=>console.log("Can't syncronize",e));
I have googled and looked up the codes creating data using sequelize.
However, writers are too good to overlook this pity but basic issue.
Where do I write the code?
Here is my directory.
Modeling
/config
config.json
/migrations
(empty)
/models
index.js
platoon.js
section.js
squad.js
team.js
/node_moduels
/seeders
(empty)
app.js
package-lock.json
package.json
The code I am trying to add on my code is
Team.bulkCreate([
{ name: 'team1', platoonID: "4" },
{ username: 'team2', platoonID: "4" },
{ username: 'team3', platoonID: "4" },
{ username: 'team4', platoonID: "4" },
{ username: 'team5', platoonID: "4" }
]).then(() => { // Notice: There are no arguments here, as of right now you'll have to...
return Team.findAll();
}).then(teams => {
console.log(teams) // ... in order to get the array of user objects
})
But the code returns
Executing (default): INSERT INTO `teams` (`id`,`name`,`created_at`,`platoonID`) VALUES (NULL,'1팀',now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4'),(NULL,NULL,now(),'4');
Executing (default): CREATE TABLE IF NOT EXISTS `platoons` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
(node:15874) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Table 'nodejs.teams' doesn't exist
at Query.formatError (/Users/mac/Desktop/modeling/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
at Query.run (/Users/mac/Desktop/modeling/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:15874) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:15874) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Executing (default): SHOW INDEX FROM `platoons` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `sections` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `sections` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `squads` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `squads` FROM `nodejs`
Executing (default): CREATE TABLE IF NOT EXISTS `teams` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(20) NOT NULL UNIQUE, `created_at` DATETIME NOT NULL DEFAULT now(), `sectionID` INTEGER, `squadID` INTEGER, `platoonID` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`sectionID`) REFERENCES `sections` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`squadID`) REFERENCES `squads` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, FOREIGN KEY (`platoonID`) REFERENCES `platoons` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `teams` FROM `nodejs`
connection succeed
I wrote this code in models/index.js.
I guess the code should be written in models/index.js, but it seems not.
How can I insert bulk data into MySQL using sequelize.bulkcreate?
models/index.js
const Sequelize = require('sequelize');
const Team = require("./team");
const Section = require("./section");
const Squad = require("./squad");
const Platoon = require("./platoon");
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Team = Team;
db.Section = Section;
db.Squad = Squad;
db.Platoon = Platoon;
Team.init(sequelize);
Section.init(sequelize);
Squad.init(sequelize);
Platoon.init(sequelize);
Team.associate(db);
Section.associate(db);
Squad.associate(db);
Platoon.associate(db);
//Team.bulkCreate([
// { name: 'team1', platoonID: "4" },
// { username: 'team2', platoonID: "4" },
// { username: 'team3', platoonID: "4" },
// { username: 'team4', platoonID: "4" },
// { username: 'team5', platoonID: "4" }
//]).then(() => {
// return Team.findAll();
//}).then(teams => {
// console.log(teams)
//})
module.exports = db;
Team.bulkCreate([
{ name: 'team1', platoonID: "4" },
{ username: 'team2', platoonID: "4" },
{ username: 'team3', platoonID: "4" },
{ username: 'team4', platoonID: "4" },
{ username: 'team5', platoonID: "4" }
]).then(() => {
return Team.findAll();
}).then(teams => {
console.log(teams)
})
models/team.js
const Sequelize = require("sequelize");
module.exports = class Team extends Sequelize.Model{
static init(sequelize) {
return super.init({
name : {
type : Sequelize.STRING(20),
allowNull : false,
unique : true,
},
created_at : {
type : Sequelize.DATE,
allowNull : false,
defaultValue : sequelize.literal('now()'),
},
},{
sequelize,
timestamps : false,
underscored : false,
modelName : 'Team',
tableName : 'teams',
paranoid : false,
charset : 'utf8',
collate : 'utf8_general_ci',
});
}
static associate(db) {
db.Team.belongsTo(db.Section, {
foreignKey : "sectionID",
targetKey : 'id'
});
db.Team.belongsTo(db.Squad, {
foreignKey : "squadID",
targetKey : 'id'
});
db.Team.belongsTo(db.Platoon, {
foreignKey : "platoonID",
targetKey : 'id'
});
};
}
I have tried to write the code in models/index.js file but it fails.
Please help where to write the code
I am getting into Loopback 4, coming from Sequelize and with a bit of experience with TypeORM.
My question is why in Loopback 4 the relations doesn't get constraints. I have seen https://loopback.io/doc/en/lb4/todo-list-tutorial-sqldb.html#specify-the-foreign-key-constraints-in-todo-model, but I don't get why it doesn't do it automatically, or if I'm doing something wrong.
Lets see an example with the same models for the three ORMS: a User model that can have many Post:
User --* Post
Sequelize:
User:
const User = sequelize.define(
'User',
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
},
},
{}
);
User.associate = function(models) {
User.hasMany(models.Post, { onDelete: 'CASCADE' });
};
Post:
const Post = sequelize.define(
'Post',
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
title: {
type: Sequelize.STRING,
},
text: {
type: Sequelize.TEXT,
},
},
{}
);
Post.associate = function(models) {
Post.belongsTo(models.User, { onDelete: 'CASCADE' });
};
Result in MYSQL:
CREATE TABLE IF NOT EXISTS `test_sequelize`.`Users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 3
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `test_sequelize`.`Posts` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NULL DEFAULT NULL,
`text` TEXT NULL DEFAULT NULL,
`UserId` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `UserId` (`UserId` ASC) ,
CONSTRAINT `posts_ibfk_1`
FOREIGN KEY (`UserId`)
REFERENCES `test_sequelize`.`Users` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 4
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
Ok, the constraints are there.
Now lets try with TypeORM:
TypeORM:
User:
import { Post } from './Post';
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: string;
#Column()
name: string;
#OneToMany(type => Post, post => post.user, { onDelete: 'CASCADE' })
posts: Post[];
}
Post:
import { User } from './User';
import { PostHasTag } from './PostHasTag';
import { Tag } from './Tag';
#Entity()
export class Post {
#PrimaryGeneratedColumn()
id: number;
#Column()
title: string;
#Column({ type: 'text' })
text: string;
#ManyToOne(type => User, user => user.posts)
user: User;
}
And this is the result in MySQL:
CREATE TABLE IF NOT EXISTS `test_typeorm`.`user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 3
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `test_typeorm`.`post` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`text` TEXT NOT NULL,
`userId` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_5c1cf55c308037b5aca1038a131` (`userId` ASC) ,
CONSTRAINT `FK_5c1cf55c308037b5aca1038a131`
FOREIGN KEY (`userId`)
REFERENCES `test_typeorm`.`user` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
AUTO_INCREMENT = 4
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
Everything ok, constraints there. Now with Loopback 4.
Loopback 4:
The models, repositories, controllers and relations are generated by the cli, but I will only post the models:
User:
import {Post} from './post.model';
#model({settings: {}})
export class User extends Entity {
#property({
type: 'number',
id: true,
generated: true,
})
id?: number;
#property({
type: 'string',
required: true,
})
name: string;
#hasMany(() => Post)
posts: Post[];
constructor(data?: Partial<User>) {
super(data);
}
}
export interface UserRelations {
// describe navigational properties here
}
export type UserWithRelations = User & UserRelations;
Post:
import {Entity, model, property} from '#loopback/repository';
#model({settings: {}})
export class Post extends Entity {
#property({
type: 'number',
id: true,
generated: true,
})
id?: number;
#property({
type: 'string',
required: true,
})
title: string;
#property({
type: 'string',
})
text?: string;
#property({
type: 'number',
})
userId?: number;
constructor(data?: Partial<Post>) {
super(data);
}
}
export interface PostRelations {
// describe navigational properties here
}
export type PostWithRelations = Post & PostRelations;
And the MySQL:
CREATE TABLE IF NOT EXISTS `test_loopback`.`Post` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(512) NOT NULL,
`text` VARCHAR(512) NULL DEFAULT NULL,
`userId` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `test_loopback`.`User` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(512) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
And as you may see, there are no constraints there. Am I doing something wrong? Is this expected behaviour?
This is a known short-coming of LoopBack, see the discussion in the following GitHub issues:
lb4 relations referential integrity for hasMany/belongsTo https://github.com/strongloop/loopback-next/issues/1718
Database migration should create SQL constraints for relations https://github.com/strongloop/loopback-next/issues/2332
and loosely related: Memory connector should enforce referential integrity https://github.com/strongloop/loopback-next/issues/2333
Loopback 4 and constraints in MySQL relations
#model({
settings: {
foreignKeys: {
fk_todo_todoListId: {
name: 'fk_todo_todoListId',
entity: 'TodoList',
entityKey: 'id',
foreignKey: 'todolistid',
},
},
},
})
export class Todo extends Entity {
//etc.
}
https://loopback.io/doc/en/lb4/todo-list-tutorial-sqldb.html#specify-the-foreign-key-constraints-in-todo-model
I have 2 tables: admin_user and admin_account.
const Sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
var admin_user = sequelize.define('admin_user', {
id: {
autoIncrement: true,
type: Sequelize.INTEGER,
primaryKey: true
},
name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
}
},
user_name:{
type: Sequelize.STRING,
allowNull: false,
unique: true
}
});
admin_user.associate = (models) =>{
admin_user.hasOne(models.admin_account, { foreignKey: 'admin_user_id' });
};
return admin_user;
};
'use strict';
const Sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
var admin_account = sequelize.define('admin_account', {
admin_user_id:{
type: Sequelize.INTEGER,
primaryKey: true
},
password: {
type: Sequelize.STRING
}
});
return admin_account;
};
and getting this error while creating the table:
Executing (default): CREATE TABLE IF NOT EXISTS admin_users (id INTEGER auto_increment , name VARCHAR(255), email VARCHAR(255) NOT NULL UNIQUE, user_name VARCHAR(255) NOT NULL UNIQUE, createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, PRIMARY KEY (id)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM admin_users FROM milkman_prod1
Executing (default): CREATE TABLE IF NOT EXISTS admin_accounts (admin_user_id INTEGER , password VARCHAR(255), createdAt DATETIME NOT NULL, updatedAt DATETIME NOT NULL, PRIMARY KEY (admin_user_id), FOREIGN KEY (admin_user_id) REFERENCES admin_users (id) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB;
Unhandled rejection SequelizeDatabaseError: Cannot add foreign key constraint
Please try with this code:
'use strict';
const Sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
var admin_account = sequelize.define('admin_user', {
admin_user_id:{
type: Sequelize.INTEGER,
primaryKey: true
},
password: {
type: Sequelize.STRING
}
});
admin_account.associate = (models) =>{
admin_account.belongsTo(models.admin_user);
};
return admin_account;
};
Working with Sequelize and MySQL database, I was trying to achieve composite primary keys combination in junction table, but unfortunately without result.
I have tables:
They are in relation many to many. In junction table user_has_project I want two primary keys combination: user_id and project_id.
Sequelize models definition:
User:
module.exports = function(sequelize, Sequelize) {
var User = sequelize.define('user', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER(11)
},
name: {
type: Sequelize.STRING(100),
allowNull: false
}
},{
timestamps: false,
freezeTableName: true,
underscored: true
});
User.associate = function (models) {
models.user.belongsToMany(models.project, {
through: 'user_has_project',
foreignKey: 'user_id',
primaryKey: true
});
};
return User;
}
Project:
module.exports = function(sequelize, Sequelize) {
var Project = sequelize.define('project', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER(11)
},
name: {
type: Sequelize.STRING(100),
allowNull: false
}
},{
timestamps: false,
freezeTableName: true,
underscored: true
});
Project.associate = function (models) {
models.project.belongsToMany(models.user, {
through: 'user_has_project',
foreignKey: 'project_id',
primaryKey: true
});
};
return Project;
}
I was trying to 'force' Primary keys definition in user_has_project table using "primaryKey: true" in both models association, but definition above is creating only user_id as PRI and project_id as MUL
What is Sequelize version? I tested Sequelize 4 in sqlite3, the definition above makes a query
CREATE TABLE IF NOT EXISTS `user_has_project` (`created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `user_id` INTEGER(11) NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, `project_id` INTEGER(11) NOT NULL REFERENCES `project` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY (`user_id`, `project_id`));
Is "PRIMARY KEY (user_id, project_id)" what you want?