Reputation: 710
I'm new to Sequelize, and trying hard to understand how this very strange, new world of ORMs works. Once thing that I can't seem to understand is the difference between ".create" and ".save" in Sequelizejs. I have written test functions with both, and besides having slightly different syntax, they both seem to do exactly the same thing.
This is using the ".save" method
models.User.build({
username: req.body.username,
password: req.body.password,
first_name: req.body.firstName,
last_name: req.body.lastName
})
.save()
.then(function(task){
// some function...
})
.catch(function(error){
// some function...
});
This is using the ".create" method
models.User.create({
username: req.body.username,
password: req.body.password,
first_name: req.body.firstName,
last_name: req.body.lastName
}).then(function(data) {
// some function...
});
What am I not seeing here?
Upvotes: 16
Views: 19749
Reputation: 8798
When used like that they mean the same thing. .create()
is internally .build()
and .save()
.
But most importantly in your first example, .build()
instantiates ActiveRecord which gains methods such as associations methods and all your getter and setter methods. The .create()
method gives you back the ActiveRecord only after the creation is completed.
Suppose your users are associated with a picture
. Sometimes you use the build method to do this:
var user = models.User.build({
userName: req.body.userName
})
// start doing things with the user instance
user.hasPictures().then(function(hasPictures) {
// does user have pictures?
console.log(hasPictures)
})
More importantly, setter methods may be of more interest to you.. See https://sequelize.org/docs/v6/core-concepts/getters-setters-virtuals/
Suppose you may have a setter
method that does this:
const User = sequelize.define('user', {
username: DataTypes.STRING,
nationality: DataTypes.STRING,
name: {
type: DataTypes.STRING,
set([firstName, lastName]) {
if (this.nationality === 'Chinese' || this.nationality === 'Korean' ) {
return this.setDataValue('name', `${lastName} ${firstName}`)
}
// for all other nationalities, we default to having the first name in front.
this.setDataValue('name', `${firstName} ${lastName}`)
}
}
})
Then now with your user
ActiveRecord, you can do:
const user = User.build({ userName: 'parkJS' })
user.nationality = 'Korean'
user.setDataValue('name', ['Ji Sung', 'Park'])
console.log(user.name) // outputs 'Park Ji Sung'
const user2 = User.build({ userName: 'davidb' })
user2.nationality = 'British'
user2.setDataValue('name', ['David', 'Beckham'])
console.log(user2.name) // outputs 'David Beckham'
// call any other setter methods here to complete the model.
// then finally call .save()
user.save()
user2.save()
Upvotes: 3
Reputation: 6105
As described in the docs http://docs.sequelizejs.com/en/latest/docs/instances/
The method .build() creates a non-persistent instance, which means that the data are not been saved on the database yet, but stored only in the memory, during the execution. When your program stops (server crash, end of the execution or something like that), instances created with .build() will be lost.
This is where .save() do its job. It stores the data of the instance built by the .build() method in the the database.
This approach allows you to manipulate instances in the way you need before storing it in the database.
The .create() method simply .build() and .save() an instance in the same command. It's a convinience for simple cases where you have no need to manipulate instances, allowing you to store the data in the database with a single command. To ilustrate:
This:
User.build({ name: "John" }).save().then(function(newUser){
console.log(newUser.name); // John
// John is now in your db!
}).catch(function(error){
// error
});
is the same as this:
User.create({ name: "John"}).then(function(newUser){
console.log(newUser.name); // John
// John is now in your db!
}).catch(function(error){
// error
});
But you can do something like this:
var user = User.build({ name: "John"}); // nothing in your db yet
user.name = "Doe"; // still, nothing on your db
user.save().then(function(newUser){
console.log(newUser.name); // Doe
// Doe is now in your db!
}).catch(function(error){
// error
});
Basically, .build() and .save() gives you the ability to modify an instance after it has been instanciated, but before you store it's data in the database.
Upvotes: 21