Reputation: 541
I have two tables named User and Gathering. I wanted to create an N:M join table by adding several columns to display the creator, likes, bookmarks for a gathering. But, An Error : lock wait timeout exceeded: try restarting transaction was caused when i tried to add User model to created Gathering model. Could you tell me what is the problem in my code??
// routing code
let putGathering = async function (req, res) {
await sequelize.transaction(async transaction => {
try {
const user = await User.findOne({
where: {
email: req.body.email,
},
}, { transaction: transaction });
const category = await Category.findOne({
where: {
category_name: req.body.categoryName,
},
}, { transaction: transaction });
const [location, created] = await Location.findOrCreate({
where: {
location_name: req.body.meetLoc,
},
transaction,
});
const gathering = await Gathering.create({
title: req.body.meetTitle,
date: req.body.meetDate,
time: req.body.meetTime,
content: req.body.content,
maxnum: req.body.maxNum,
minnum: req.body.minNum,
maxage: req.body.maxAge,
minage: req.body.minAge,
}, { transaction: transaction });
await category.addGathering(
gathering,
{ transaction },
);
await location.addGathering(
gathering,
{ transaction },
);
console.log(10); // This log is worked.
await gathering.addUser(
user,
{
through: {
status: 1,
like: 0,
book_mark: 0,
}
},
{ transaction },
);
console.log(11); // This log is not worked. I think there is a problem int upper code.
res
.status(201)
.json({
responseMsg: 'succeed',
})
} catch (err) {
console.error(err);
}
});
};
// user.js(Sequelize Model file)
const Sequelize = require('sequelize');
module.exports = class User extends Sequelize.Model {
static init(sequelize) {
return super.init({
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
email: {
type: Sequelize.STRING,
allowNull: false,
validate: {
isEmail: true
},
},
pw: {
type: Sequelize.STRING,
allowNull: false
},
phone: {
type: Sequelize.CHAR(15),
allowNull: false
},
nickname: {
type: Sequelize.STRING(10),
allowNull: false
},
gender: {
type: Sequelize.CHAR(1),
allowNull: false
},
who: {
type: Sequelize.INTEGER,
allowNull: false
},
introduction: {
type: Sequelize.TEXT
},
userImg: {
type: Sequelize.STRING
},
birth: {
type: Sequelize.DATE,
allowNull: false
},
salt: {
type: Sequelize.STRING
},
}, {
sequelize,
timestamps: true,
underscored: true,
paranoid: true,
modelName: 'user',
tableName: 'User',
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.User.belongsToMany(db.Gathering, {
through: db.UserGathering,
foreignKey: 'user_idx',
timestamps: false
});
}
};
// gathering.js(Sequelize Model file)
const Sequelize = require('sequelize');
module.exports = class Gathering extends Sequelize.Model {
static init(sequelize){
return super.init({
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
title: {
type: Sequelize.STRING,
allowNull: false,
},
date: {
type: Sequelize.STRING,
allowNull: false
},
time: {
type: Sequelize.STRING,
allowNull: false
},
content: {
type: Sequelize.TEXT,
allowNull: false
},
maxnum: {
type: Sequelize.INTEGER,
allowNull: false
},
minnum: {
type: Sequelize.INTEGER,
allowNull: false
},
maxage: {
type: Sequelize.INTEGER,
allowNull: false
},
minage: {
type: Sequelize.INTEGER,
allowNull: false
}
}, {
sequelize,
timestamps: true,
underscored: true,
paranoid: true,
modelName: 'gathering',
tableName: 'Gathering',
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.Gathering.belongsToMany(db.User, {
through: db.UserGathering,
foreignKey: 'gathering_idx',
timestamps: false
});
}
};
// user_gathering.js(Sequelize Model)
const Sequelize = require('sequelize');
module.exports = class UserGathering extends Sequelize.Model {
static init(sequelize) {
return super.init({
status: {
type: Sequelize.INTEGER,
},
like: {
type: Sequelize.INTEGER,
},
book_mark: {
type: Sequelize.INTEGER,
},
}, {
sequelize,
timestamps: false,
modelName: 'userGathering',
tableName: 'User_Gathering',
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
};
// index.js (for Sequelize Config)
const Sequelize = require('sequelize');
const User = require('./user');
const Category = require('./category');
const Gathering = require('./gathering');
const Location = require('./location');
const Comment = require('./comment');
const UserGathering = require('./user_gathering');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.User = User;
db.Category = Category;
db.Gathering = Gathering;
db.Location = Location;
db.Comment = Comment;
db.UserGathering = UserGathering;
User.init(sequelize);
Category.init(sequelize);
Gathering.init(sequelize);
Location.init(sequelize);
Comment.init(sequelize);
UserGathering.init(sequelize);
User.associate(db);
Gathering.associate(db);
Location.associate(db);
Category.associate(db);
Comment.associate(db);
UserGathering.associate(db);
module.exports = db;
// error log
0|app | { Error: Lock wait timeout exceeded; try restarting transaction
0|app | at Packet.asError (/home/ec2-user/mepus_test/node_modules/my sql2/lib/packets/packet.js:712:17)
0|app | at Query.execute (/home/ec2-user/mepus_test/node_modules/mys ql2/lib/commands/command.js:28:26)
0|app | at Connection.handlePacket (/home/ec2-user/mepus_test/node_m odules/mysql2/lib/connection.js:425:32)
0|app | at PacketParser.Connection.packetParser.p [as onPacket] (/ho me/ec2-user/mepus_test/node_modules/mysql2/lib/connection.js:75:12)
0|app | at PacketParser.executeStart (/home/ec2-user/mepus_test/node _modules/mysql2/lib/packet_parser.js:75:16)
0|app | at Socket.Connection.stream.on.data (/home/ec2-user/mepus_te st/node_modules/mysql2/lib/connection.js:82:25)
0|app | at Socket.emit (events.js:198:13)
0|app | at addChunk (_stream_readable.js:288:12)
0|app | at readableAddChunk (_stream_readable.js:269:11)
0|app | at Socket.Readable.push (_stream_readable.js:224:10)
0|app | code: 'ER_LOCK_WAIT_TIMEOUT',
0|app | errno: 1205,
0|app | sqlState: 'HY000',
0|app | sqlMessage: 'Lock wait timeout exceeded; try restarting transa ction',
0|app | sql:
0|app | 'INSERT INTO `User_Gathering` (`status`,`like`,`book_mark`,`u ser_idx`,`gathering_idx`) VALUES (1,0,0,1,7);',
0|app | parameters: undefined },
Upvotes: 1
Views: 385
Reputation: 26
The syntax for the method Model.belongsToMany.add() is:
entityA.addEntityB(entityB: Model, ... , options: object)
The solution is to include both through
and transaction
, not as separate parameters, but in the same options
object.
await gathering.addUser(
user,
{
through: {status: 1, like: 0, book_mark: 0},
transaction: transaction
}
);
You might already solved it but I had the same confusion and couldn't find useful results, so I think it's worth it to share a solution.
Upvotes: 1