Difference between HasOne and BelongsTo in Sequelize ORM - node.js

I am developing a sails.js app with sequelize ORM. I am a little confused as to when BelongsTo and HasOne need to be used.
The documentation states that :
BelongsTo associations are associations where the foreign key for the
one-to-one relation exists on the source model.
HasOne associations are associations where the foreign key for the
one-to-one relation exists on the target model.
Is there any other difference apart from the the place where these are specified? Does the behavior still continue to be the same in either cases?

This is more universal problem.
The main difference is in semantic. you have to decide what is the relationship (Some silly example):
Man has only one right arm. Right arm belongs to one man.
Saying it inversely looks a little weird:
Right arm has a man. A man belongs to right arm.
You can have man without right arm. But alone right arm is useless.
In sequelize if RightArm and Man are models, it may looks like:
Man.hasOne(RightArm); // ManId in RigthArm
RightArm.belongsTo(Man); // ManId in RigthArm
And as you notice there is also difference in db table structure:
BelongsTo will add the foreignKey on the source where hasOne will add on the target (Sequelize creates new column 'ManId' in table 'RightArm' , but doesn't create 'RightArmId' column in 'Man' table).
I don't see any more differences.

I agree with Krzysztof Sztompka about the difference between:
Man.hasOne(RightArm);
RightArm.belongsTo(Man);
I'd like to answer Yangjun Wang's question:
So in this case, should I use either Man.hasOne(RightArm); or
RightArm.belongsTo(Man);? Or use them both?
It is true that the Man.hasOne(RightArm); relation and the RightArm.belongsTo(Man); one do the same thing - each of these relations will add the foreign key manId to the RightArm table.
From the perspective of the physical database layer, these methods do the same thing, and it makes no difference for our database which exact method we will use.
So, what's the difference? The main difference lays on the ORM's layer (in our case it is Sequalize ORM, but the logic below applies to Laravel's Eloquent ORM or even to Ruby's Active Record ORM).
Using the Man.hasOne(RightArm); relation, we will be able to populate the man's RightArm using the Man model. If this is enough for our application, we can stop with it and do not add the RightArm.belongsTo(Man); relation to the RightArm model.
But what if we need to get the RightArm's owner? We won't be able to do this using the RightArm model without defining the RightArm.belongsTo(Man); relation on the RightArm model.
One more example will be the User and the Phone models. Defining the User.hasOne(Phone) relation, we will be able to populate our User's Phone. Without defining the Phone.belongsTo(User) relation, we won't be able to populate our Phone's owner (e.g. our User). If we define the Phone.belongsTo(User) relation, we will be able to get our Phone's owner.
So, here we have the main difference: if we want to be able to populate data from both models, we need to define the relations (hasOne and belongsTo) on both of them. If it is enough for us to get only, for example, User's Phone, but not Phone's User, we can define only User.hasOne(Phone) relation on the User model.
The logic above applies to all the ORMs that have hasOne and belongsTo relations.
I hope this clarifies your understanding.

I know this is a 4-years late answer, but I've been thinking of it, searching the docs, and googling since yesterday. And couldn't find an answer that convinced me about what was happening. Today I've got to a conclusion: the difference is not just a matter of semantics, definitely!
Let's suppose you have the following statement (from the docs):
Project.hasMany(Task);
It creates, in Project model, some utility methods on the instances of Project, like: addTask, setTask etc. So you could do something like:
const project = await Project.create({...});
// Here, addTask exists in project instance as a
// consequence of Project.hasMany(Task); statement
project.addTasks([task1, task2]);
Also, in the database, a foreign key in tasks relation would've been created, pointing to projects relation.
Now if, instead of Project.hasMany(Task);, I had stated only:
Task.belongsTo(Project);
Then, similarly, in the database, foreign keys in tasks relation would've been created, pointing to projects relation. But there wouldn't be any addTasks method on project instances though. But, by doing Task.belongsTo(Project);, Sequelize would create a different set of methods, but only on task instances this time. After doing that, you could associate a task to a project using, for example:
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);
The docs defines as source, the model that owns the method used to create the association. So, in:
Project.hasMany(Task);: In this statement, Project is the source model. Task is, in turn, the target model.
Task.belongsTo(Project);: In this statement, Task is the source model. Project is, in turn, the target model.
The thing is that, when creating associations using hasOne, hasMany, belongsTo, and belongsToMany, the instances utility methods are created only on the source model. In summary: if you want to have the utility methods created both in Project and Task instances, you must use the two statements for describing the same the association. In the database itself, both will have the same redundant effect (creating a foreign key on tasks relation pointing to projects relation's primary key):
// 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);
BTW, after writing this answer, I realized that this is the same thing that Vladsyslav Turak is explaining in his answer, but I decided to keep my answer here because it adds some important practical information involving the utility methods stuff.

One-to-One belongTo or hasOne
Using the right arm example, and Sequelize's own documentation. The question we must ask is, can a man survive without a right arm? Or can a right arm survive without a man? To determine where we want our foreign key to exist is to answer this question. Let's take a more practical example.
Let's say you have a community website. Your users are all represented by a singular Profile model (or User model). But in a community you will also have administrators and moderators, both with their own sets of rights, and maybe even a different kind of profile. Instead of adding admin/mod specific fields to the User model, it might be best to create a separate model to represent an admin/mod.
Here's what basic user model looks like (ignoring constraints and validations):
class User extends Model {
static associate(models) {}
}
User.init(
{
username: DataTypes.STRING(25),
password: DataTypes.STRING(50)
}
)
Now here's a model that represents an admin or mod, which is intended to extend the user model:
class Staff extends Model {
static associate(models) {}
{
Staff.init(
{
permissions: DataTypes.ARRAY(DataTypes.STRING),
roleType: DataTypes.STRING(20),
}
)
So we ask our selves, can a user exist without admin/mod? Can an admin/mod exist without a user? A user doesn't have to be staff to use your services, but an admin/mod still needs a username and password in order to login. You could add those fields to the Staff model, but the truth is, it would be repeating information and make things harder to keep track of.
At the heart, an admin/mod would have the same attributes as a normal user, just with special abilities. If you intend otherwise, I'd still maintain a BaseUser model to organize and keep what each model has in common together. An admin/mod account would still have a username and password, and likely an email as well. Otherwise, you'd end up having two users with the same info, and in a community that can be confusing, and difficult to manage.
It is determined that a user does not need a Staff object associated with it to exist, so we shouldn't put the foreign key on the user profile. This still doesn't quite answer our question though. Remember, hasOne() puts the FK on the target model, while belongsTo() places the FK on the source. So we could say that Staff.belongsTo(User) or User.hasOne(Staff) that meets the requirement of the FK has to exist on the Staff model.
Whether you put a belongsTo() on the Staff model, or a hasOne() on the User model is a matter of semantics, and doesn't really matter. Either will associate the Staff model with the User model, allowing you to perform the User.getStaff() method. If you want to be able to get user account from a Staff instance, you could add a reference column without creating an actual association like so on our Staff model (this doesn't add constraints or associations, merely as it implies, a reference):
user: {
type: DataTypes.INTEGER,
references: {
model: User,
key: 'userId'
}
}
I hope this helps.

Related

Domain model defining relationships

Assuming everyone has the rights to do the CRUD operations (everyone is an admin type user). I have displayed CRUD operations the user can perform in the Domain diagram however, it's become quite messy. I am curious if it's acceptable to do the alternative approach shown in the images below instead since the multiplicative relationships remain the same for each action (create,edit,delete)
Seperated CRUD
Alternative approach? (create, edit, delete)
In short
If it becomes messy, it probably lacks of separation of concerns, or represents associations that are not really needed.
More explanations
Are the associations needed?
An association between User and Xxx implies a semantic relationship between the two classes. This means that instances of the classes are linked and not just for the time of an operations. So x would be able to find the User(s) that updated it, and u would know the Xxx instances that it updated. This kind of association can make sense if you want some audit trails, but this seems not to be your purpose here.
In other words, the fact that a User may perform some operations that CRUD instances of Xxx is not sufficient for justifying an association.
If they are needed, do they represent what you think?
Now it appears that your associations are can ..., i.e. some kind of authorisation scheme. Your diagram tells that each user would need to know in advance all the Xxx that it could update. This is a heavy burden. It would also imply that a user needs to know all the Xxx it can create; before they are even created? This looks somewhat inconsistent.
Modeling an authorisation scheme
If you'd wand to design an authorisation system, you'd probably not link users directly to the object, but use some intermediary mechanisms:
To express that a user can create new projects, you'd probably have some authorisation object that tells the caracteristics of projects that can be created.
To express that a user can edit, update, delete projcts, you could have a direct association like you envisaged, if some admin would maintain such authorisations.
But probably you would have some authorisation object that would tell what a user can do (e.g. a user "role"/"profile") and what category of projects.
Equally probable is that there are some rules that govern CRUD authorisations (e.g. a user having the role "edit" can edit the project he/she is assigned to, but not the others). Making use of such rules instead of explicitly designing (redundant) authorisations could then save you a lot of unnecessary extra associations (and extra constraints to keep the authorisations consistent with the rules).
Separation of concerns
And to keep things continue to be messy, you should consider:
having a separate diagram in your model for the authorisation concept
use some common CRUD interface: the users would then be associated with the CRUD interface without having to replicate everything for every possible class.
The main issue with both of your class models is a confusion between the type/instance levels. Your "can create/edit/delete" authorization relationships do not hold between a specific user and a specific object (an instance of Company, Project or Ticket), but rather between a specific user and a sepcific object type (Company, Project or Ticket), so it's not an ordinary association between two ordinary object types.
If you want to describe/define such authorization relationships with a class model, you would need to define a meta-class like ObjectType and express that your object types (Company, Project or Ticket) are instances of it.

Too many associations, aggregations or compositions in a class diagram?

We're tasked to make a system that will record students daily in and out of the institution premises via student ID, to ensure student safety, and The instructor can also use this system as the student attendance.
Can you help me by checking if this is correct or any improvement is required?
In short
There are some syntactic issues with the associations in your diagram.
Moreover, associations correspond to a structural relationship. Do not create associations, simply because one class uses another at some point in time: for a simple use, a «use» dependency is the most you can do.
More details
Syntactically, this diagram seems correct, except for the label on the association:
Since it's in the middle of the line, we assume it's the association name. But the association name has no visibility.
Since there is a - (private) visibility, we understand that it could be the role of an association end. But It should then be located on the end and not in the middle.
Semantically, from an UML point of view there are some suspicious relationships:
The double composition of Login is probably wrong: composition indicates an exclusive ownership. Your diagram says that a Login occurence is owned either by an Admin or by a Teacher but if it's owned by one, the other cannot be related to it.
Moreover, composition suggest a part-whole relationship and I don't see a login to "be a part of" a teacher or an admin.
The aggregation is not well defined in UML and therfore does not really add value. Some people see it suggesting a part§whole relation with non-exclusive ownership: in this case it would be wrong. Better get rid of it.
The name of the Validates association is confusing as it corresponds to a Login's operation. It might lead to think that the line corresponds to the dynamic invocation of the operation, whereas in reality an association is structural.
But it's difficult to say more in absence of any requirement or analysis context. Based on my domain knowledge:
The 1 to 1 association between Admin and Student must be wrong, since an Admin may enrol 0 users (new admin), or many users
There's a login which is probably used to monitor the in's of the students, but nothing seems to monitor the outs.
Do each student have only one single teacher ?
It's not clear to me if all these associations are a structural relation. For example, we can understand that at a point in time, in a transaction, a teacher validates a login. But should a trace of this validation be kept (i.e. do you expect to be able to later find out all the logins that a teacher has validated? or to find for a given login which teacher did validate it?).

What's the benefit of `BelongsTo` relation?

What's the benefit of defining BelongsTo relation?
When I defined HasMany relation I could execute all my queries without missing anyone (I prefer to give me an example in case you find it's important to use BelongsTo relation).
The benefit is being able to flip the "base" and "child" in of the relation. LoopBack 4 relation filters are akin to an SQL LEFT JOIN, meaning that the filter must be scoped from the base model.
From the "Filtering by parent model" docs:
Where filters such as those used by model queries (create(), find(), replaceById(), and so on) cannot be used to filter a model by the value of its parent model. See its GitHub issue.
For example, we may have many Orders made by a Customer:
#hasMany(() => Order)
orders?: Order[];
This relation enables querying for "orders made by a customer" or "orders made by a list of filtered customers", but not the other way around; "the customer that made that order" or "the customers that made a list of filtered orders".
A Belongs To relation solves this by creating a key on the Order that references a Customer:
#belongsTo(() => Customer)
customerId: number;
This means that we can now query "which customer made that order" or "which customers made the filtered list of orders".
Another important factor is that a Has Many relation can't be made into a Strong Relation as ANSI SQL does not have a method of representing such relations. From the docs:
LoopBack 4 implements weak relations with #belongsTo(), #hasMany(), #hasOne(), etc. This means the constraints are enforced by LoopBack 4 itself, not the underlying database engine. This is useful for integrating cross-database relations, thereby allowing LoopBack 4 applications to partially take the role of a data lake.
However, this means that invalid data could be keyed in outside of the LoopBack 4 application. To resolve this issue, some LoopBack 4 connectors (such as PostgreSQL and MySQL) allow defining a foreign key constraint through the #model() decorator. Please consult the respective connector documentation to check for compatibility.
Emphasis in italics is mine on why these restrictions apply.

How to handle Persistence with Rich Domain Model

I am redesigning my NodeJS application because I want to use the Rich Domain Model concept. Currently I am using Anemic Domain Model and this is not scaling well, I just see 'ifs' everywhere.
I have read a bunch of blog posts and DDD related blogs, but there is something that I simply cannot understand... How do we handle Persistence properly.
To start, I would like to describe the layers that I have defined and their purpose:
Persistence Model
Defines the Table Models. Defines the Table name, Columns, Keys and Relations
I am using Sequelize as ORM, so the Models defined with Sequelize are considered my Persistence Model
Domain Model
Entities and Behaviors. Objects that correspond to the abstractions created as part of the Business Domain
I have created several classes and the best thing here is that I can benefit from hierarchy to solve all problems (without loads of ifs yay).
Data Access Object (DAO)
Responsible for the Data management and conversion of entries of the Persistence Model to entities of the Domain Model. All persistence related activities belong to this layer
In my case DAOs work on top of the Sequelize models created on the Persistence Model, however, I am serializing the records returned on Database Interactions in different objects based on their properties. Eg.: If I have a Table with a column called 'UserType' that contains two values [ADMIN,USER], when I select entries on this table, I would serialize the return according to the User Type, so a User with Type: ADMIN would be an instance of the AdminUser class where a User with type: USER would simply be a DefaultUser...
Service Layer
Responsible for all Generic Business Logic, such as Utilities and other Services that are not part of the behavior of any of the Domain Objects
Client Layer
Any Consumer class that plays around with the Objects and is responsible in triggering the Persistence
Now the confusion starts when I implement the Client Layer...
Let's say I am implementing a new REST API:
POST: .../api/CreateOrderForUser/
{
items: [{
productId: 1,
quantity: 4
},{
productId: 3,
quantity: 2
}]
}
On my handler function I would have something like:
function(oReq){
var oRequestBody = oReq.body;
var oCurrentUser = oReq.user; //This is already a Domain Object
var aOrderItems = oRequestBody.map(function(mOrderData){
return new OrderItem(mOrderData); //Constructor sets the properties internally
});
var oOrder = new Order({
items: aOrderItems
});
oCurrentUser.addOrder(oOrder);
// So far so good... But how do I persist whatever
// happened above? Should I call each DAO for each entity
// created? Like, first create the Order, then create the
// Items, then update the User?
}
One way I found to make it work is to merge the Persistence Model and the Domain Model, which means that oCurrentUser.addOrder(...) would execute the business logic required and would call the OrderDAO to persist the Order along with the Items in the end. The bad thing about this is that now the addOrder also have to handle transactions, because I don't want to add the order without the items, or update the User without the Order.
So, what I am missing here?
Aggregates.
This is the missing piece on the story.
In your example, there would likely not be a separate table for the order items (and no relations, no foreign keys...). Items here seem to be values (describing an entity, ie: "45 USD"), and not entities (things that change in time and we track, ie: A bank account). So you would not directly persist OrderItems but instead, persist only the Order (with the items in it).
The piece of code I would expect to find in place of your comment could look like orderRepository.save(oOrder);. Additionally, I would expect the user to be a weak reference (by id only) in the order, and not orders contained in a user as your oCurrentUser.addOrder(oOrder); code suggests.
Moreover, the layers you describe make sense, but in your example you mix delivery concerns (concepts like request, response...) with domain concepts (adding items to a new order), I would suggest that you take a look at established patterns to keep these concerns decoupled, such as Hexagonal Architecture. This is especially important for unit testing, as your "client code" will likely be the test instead of the handler function. The retrieve/create - do something - save code would normally be a function in an Application Service describing your use case.
Vaughn Vernon's "Implementing Domain-Driven Design" is a good book on DDD that would definitely shed more light on the topic.

DDD saving "same" entity for different context boundaries

This is only an example.
Say that you have 2 entities for 2 different context boundaries. The first context is the SkillContexter, the entity is 'Player' and has 3 properties: Id, Name and SkillLevel. In the other context (Contactcontext) the entity is 'Player' and has 3 properties: Id, Name and EMail.
How do I persist these entities to the database? I only want one table (Player) and not two tables (PlayerContact, PlayerSkill). Shall I have two different repositories for player that save the different context-entities, but into same table? Or shall I have a "master" player entity that holds all properties that I need to save, so that I create a new entity called PlayerMaster that has 4 properties: Id, Name, EMail and SkillLevel?
The first solution gives me more repositories, and the second makes me make a "technical" entity that only purpose is to save data to a database, and that feels really wrong, or is there a better solution that I have missed?
How have you guys solved it?
When I first started with DDD, I also wrestled with the Context + Domain + Module + Model organization of things as well.
DDD is really meant to be a guide to building your domain models. Once I stopped trying to sub-organize my Contexts and boundies, and started thinking of what really is shared between entities - things started to fit together better.
I actually do not use contexts, unless it is a completely different application (app = context). Just my preference. But, I do have Modules that only share base abstracts and interfaces common throughout code (IRepository, IComponent, etc). The catch is, DDD says that Modules can share entities between modules - but, only on a very limited scale (you really don't want to do it often).
With that in mind, I would get away from using contexts and move to a "what really am I trying to accomplish, what do these models have in common). Here's what I would think, reading your question (if I understand them).
Person() is a base entity. It has ID and Name.
PlayerSkill() is a Value Object, that is
accessable from Person().PlayerSkill.
Contact() is an entity that inherits Person(),
so it inherits ID and Name, and has additional Contact properties you want.
Now, I just tore up your domain. I know.
You can use a hybird approach as well:
Person() is a base entity. It has ID and Name.
Player() inherits Person(), applies Skill()
and other VOs.
Contact() inherits Person(), applies Address()
and other VOs.
I'm not quite sure what you mean by context boundaries, so my answer may be off.
Do the two Player entities represent the same physical entity (person)? If so, then I would create a single Player entity with all four attributes and store their data in a single table.

Resources