发布于 2016-01-02 20:38:17
这是一个更普遍的问题。
主要的区别在于语义上。你必须决定什么是关系(一些愚蠢的例子):
人只有一只右臂。右臂属于一个人。
相反地说它看起来有点奇怪:
右臂有个男人。一个人属于右臂。
你可以拥有没有右臂的男人。但单靠右臂是没用的。
如果RightArm和Man是模型的话,它可能看起来像:
Man.hasOne(RightArm); // ManId in RigthArm
RightArm.belongsTo(Man); // ManId in RigthArm正如您注意到的,db表结构也有差异:
BelongsTo将在hasOne将添加到目标的源上添加foreignKey (Sequelize将在表“RightArm”中创建新列“ManId”,但不会在“Man”表中创建“RightArmId”列)。
我看不出还有什么不同之处。
发布于 2018-05-06 10:56:06
我同意克孜兹托夫关于以下几个方面的区别:
Man.hasOne(RightArm);
RightArm.belongsTo(Man);我想回答王阳军的问题:
因此,在这种情况下,我应该使用
Man.hasOne(RightArm);还是RightArm.belongsTo(Man);?还是两者兼用?
确实,Man.hasOne(RightArm);关系和RightArm.belongsTo(Man);关系做了相同的事情--每个关系都会将外键manId添加到RightArm表中。
从物理数据库层的角度来看,这些方法做了同样的事情,对于我们的数据库来说,我们将使用哪一种精确的方法并没有什么区别。
那么,有什么区别呢?主要的区别在于ORM的层(在我们的例子中它是均衡化 ORM,但下面的逻辑适用于Laravel的雄辩 ORM,甚至适用于活动记录 ORM)。
使用Man.hasOne(RightArm);关系,我们将能够使用Man模型填充男人的RightArm。如果这对我们的应用程序来说已经足够了,我们可以停止使用它,不要将RightArm.belongsTo(Man);关系添加到RightArm模型中。
但是,如果我们需要得到RightArm的所有者呢?如果不在RightArm模型上定义RightArm.belongsTo(Man);关系,我们就无法使用RightArm模型来完成这个任务。
另外一个例子是User和Phone模型。定义User.hasOne(Phone)关系,我们就可以填充User的Phone,不定义Phone.belongsTo(User)关系,就无法填充Phone的所有者(例如User),如果定义Phone.belongsTo(User)关系,就可以得到Phone的所有者。
因此,这里我们有一个主要的区别:如果我们想要填充来自这两个模型的数据,我们需要定义它们的关系(hasOne和belongsTo)。如果我们只需要得到User的Phone,而不能得到Phone的User,我们就只能在User模型上定义User.hasOne(Phone)关系。
上面的逻辑适用于所有具有hasOne和belongsTo关系的ORM。
我希望这能澄清你的理解。
发布于 2020-05-05 19:43:42
我知道这是一个4年后的回答,但我一直在考虑,搜索文档,并搜索从昨天开始。却找不到一个能让我相信发生了什么的答案。今天我得出了一个结论:区别是,而不是,绝对是一个语义问题!
假设您有以下语句(从医生那里):
Project.hasMany(Task);在Project模型中,它在Project实例上创建了一些实用方法,如:addTask、setTask等。因此,您可以这样做:
const project = await Project.create({...});
// Here, addTask exists in project instance as a
// consequence of Project.hasMany(Task); statement
project.addTasks([task1, task2]);此外,在数据库中,将在tasks关系中创建一个外键,指向projects关系。
现在,如果不是Project.hasMany(Task);,我只说了:
Task.belongsTo(Project);然后,类似地,在数据库中,将创建tasks关系中的外键,指向projects关系。但是,在addTasks实例上不会有任何project方法。但是,通过执行task,Sequelize将创建一组不同的方法,但这次只能在Task.belongsTo(Project);实例上使用。这样做之后,您可以使用以下方法将任务与项目关联起来:
const proj = await Project.findByPk(...);
const task1 = await Task.create({...});
...
// Here, setProject exists in task instance as a
// consequence of Task.belongsTo(Project); statement
task1.setProject(proj);文档定义为源,该模型拥有用于创建关联的方法。因此,在:
Project.hasMany(Task);:在这个语句中,Project是源模型。Task反过来又是目标模型。Task.belongsTo(Project);:在这个语句中,Task是源模型。Project反过来又是目标模型。问题是,当使用hasOne、hasMany、belongsTo和belongsToMany创建关联时,实例实用程序方法仅在源模型上创建。总之:如果您希望在Project和Task实例中同时创建实用程序方法,则必须使用这两个语句来描述相同的关联。在数据库本身中,两者具有相同的冗余效果(在tasks关系上创建指向projects关系的主键的外键):
// All the instances of Project model will have utility methods
Project.hasMany(Task);
// All the instances of Task model will have utility methods
Task.belongsTo(Project);
const project = await Project.create(...);
const task1 = await Task.create(...);
const task2 = await Task.create(...);
...
// as a consequence of Project.hasMany(Task), this can be done:
project.addTask(task1);
...
// as a consequence of Task.belongsTo(Project), this can be done:
task2.setProject(project);顺便说一句,写完这个答案后,我意识到这和弗拉季斯拉夫图拉克在他的回答中解释的一样,但是我决定在这里保留我的答案,因为它增加了一些重要的实用信息,包括实用方法之类的东西。
https://stackoverflow.com/questions/34565360
复制相似问题