Jas*_*bas 33 orm node.js sequelize.js
我正在用sequelize ORM 开发一个sails.js应用程序.关于什么时候需要使用BelongsTo和HasOne,我有点困惑.
文件指出:
BelongsTo关联是源模型上存在一对一关系的外键的关联.
HasOne关联是目标模型上存在一对一关系的外键的关联.
除了指定这些之外还有其他区别吗?在任何一种情况下,这种行为是否仍然相同?
Krz*_*pka 60
这是更普遍的问题.
主要区别在于语义.你必须决定什么是关系(一些愚蠢的例子):
男人只有一只右臂.右臂属于一个人.
说它反过来看起来有点奇怪:
右臂有一个男人.一个男人属于右臂.
你可以让男人没有右臂.但是单独的右臂是无用的.
在续集中如果RightArm和Men是模型,它可能看起来像:
Man.hasOne(RightArm);
RightArm.belongsTo(Man);
Run Code Online (Sandbox Code Playgroud)
正如您所注意到的,db表结构也存在差异:
BelongsTo将在源头上添加foreignKey,其中hasOne将在目标上添加(Sequelize在表'RightArm'中创建新列'ManId',但不在'Man'表中创建'RightArmId'列).
我没有看到任何更多的分歧.
Vla*_*rak 45
我同意Krzysztof Sztompka关于以下两者之间的区别:
Man.hasOne(RightArm);
RightArm.belongsTo(Man);
Run Code Online (Sandbox Code Playgroud)
我想回答杨俊君的问题:
所以在这种情况下,我应该使用
Man.hasOne(RightArm);或者RightArm.belongsTo(Man);?或者两者兼用?
确实,Man.hasOne(RightArm);关系和RightArm.belongsTo(Man);一个人做同样的事情 - 这些关系中的每一个都会将外键添加manId到RightArm表中.
从物理数据库层的角度来看,这些方法做了同样的事情,对我们的数据库来说,我们将使用的确切方法没有区别.
那么,有什么区别?主要的区别奠定了ORM的层上(在我们的情况下,它是Sequalize ORM,但下面的逻辑也适用于Laravel的雄辩 ORM甚至Ruby的活动记录 ORM).
使用该Man.hasOne(RightArm);关系,我们将能够RightArm使用该Man模型填充该人.如果这对我们的应用程序来说足够了,我们可以停止它并且不要将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.hasOne(Phone)在关系User模型.
上面的逻辑适用于所有具有hasOne和belongsTo关系的ORM .
我希望这能澄清你的理解.
我知道这是一个迟到 4 年的答案,但我一直在思考它,从昨天开始搜索文档和谷歌搜索。并且找不到让我相信正在发生的事情的答案。今天,我有一个结论:不同的是不只是语义的事,绝对!
假设您有以下语句(来自文档):
Project.hasMany(Task);
Run Code Online (Sandbox Code Playgroud)
它创建,在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]);
Run Code Online (Sandbox Code Playgroud)
此外,在数据库中,tasks将创建关系中的外键,指向projects关系。
现在,如果,而不是Project.hasMany(Task);,我只说:
Task.belongsTo(Project);
Run Code Online (Sandbox Code Playgroud)
然后,类似地,在数据库中,tasks将创建关系中的外键,指向projects关系。但是addTasks在project实例上不会有任何方法。但是,通过这样做Task.belongsTo(Project);,Sequelize 将创建一组不同的方法,但这次只在task实例上。这样做之后,您可以使用以下方法将任务与项目相关联:
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);
Run Code Online (Sandbox Code Playgroud)
文档定义为source,该模型拥有用于创建关联的方法。所以,在:
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);
Run Code Online (Sandbox Code Playgroud)
顺便说一句,写完这个答案后,我意识到这与Vladsyslav Turak在他的答案中解释的内容相同,但我决定将答案保留在这里,因为它添加了一些涉及实用方法的重要实用信息。
| 归档时间: |
|
| 查看次数: |
8867 次 |
| 最近记录: |