Difference Between One-To-Many, Many-To-One and Many-To-Many

Difference Between One-to-Many, Many-to-One and Many-to-Many?

One-to-Many: One Person Has Many Skills, a Skill is not reused between Person(s)

  • Unidirectional: A Person can directly reference Skills via its Set
  • Bidirectional: Each "child" Skill has a single pointer back up to the
    Person (which is not shown in your code)

Many-to-Many: One Person Has Many Skills, a Skill is reused between Person(s)

  • Unidirectional: A Person can directly reference Skills via its Set
  • Bidirectional: A Skill has a Set of Person(s) which relate to it.

In a One-To-Many relationship, one object is the "parent" and one is the "child". The parent controls the existence of the child. In a Many-To-Many, the existence of either type is dependent on something outside the both of them (in the larger application context).

Your subject matter (domain) should dictate whether or not the relationship is One-To-Many or Many-To-Many -- however, I find that making the relationship unidirectional or bidirectional is an engineering decision that trades off memory, processing, performance, etc.

What can be confusing is that a Many-To-Many Bidirectional relationship does not need to be symmetric! That is, a bunch of People could point to a skill, but the skill need not relate back to just those people. Typically it would, but such symmetry is not a requirement. Take love, for example -- it is bi-directional ("I-Love", "Loves-Me"), but often asymmetric ("I love her, but she doesn't love me")!

All of these are well supported by Hibernate and JPA. Just remember that Hibernate or any other ORM doesn't give a hoot about maintaining symmetry when managing bi-directional many-to-many relationships...thats all up to the application.

Difference between one-to-many and many-to-one relationship

Yes, it is vice versa. It depends on which side of the relationship the entity is present on.

For example, if one department can employ several employees then department to employee is a one-to-many relationship (1 department employs many employees), while employee to department relationship is many-to-one (many employees work in one department).

More info on the relationship types:

Database Relationships - IBM DB2 documentation

Difference between using @OneToMany and @ManyToMany

Well, the difference is in the design you're trying to reflect using objects.

In your case, every Question can be assigned to multiple Categories - so that's a sign of @*ToMany relationship. Now you have to decide if:

  • each Category can have only one Question assigned to it (it will result in a unique constraint which means that no other Category can refer the same Question) - this will be @OneToMany relationship,
  • each Category can have multiple Questions assigned to it (there will be no unique constraint in the Category table) - this will be @ManyToMany relationship.

@OneToMany (Question -> Category)

This relationship can be represented by join table only if you explicitly define so using @JoinTable or when it is a unidirectional relationship in which the owning side is the 'One' side (it means that in the Question entity you have a collection of Categories, but in the Categories you don't have any reference to the Question).

If you think about it, it seems quite reasonable that the join table is used. There is no other way the DBMS could save a connection between one row in Question table with multiple rows in Categories table.

However, if you would like to model a bidirectional relationship you need to specify that the Category ('Many' side) is the owning side of the relationship. In this case the DBMS can create a join column with foreign key in the Category table because each Category row can be connected with only one Question.

In this way you don't have any join table but simple foreign keys (still, as pointed at the beginning, you can force to create the join table using @JoinTable).

@ManyToMany

This relationship must be represented as a join table. It basically works very similar to the unidirectional @OneToMany relationship, but in this case you may have multiple rows from Question joined with multiple rows from Categories.

django difference between - one to one, many to one and many to many

Especially with django, which makes complicated db design a piece of cake, I think it's very important to understand how they work on the SQL level to better understand anything you are doing. I think an example is the best way to understand this.

First thing you should understand is that each SQL table has one field (which is usually automatically incremented) which is called a 'primary-key'. This field is a column with a unique value for each row.

Say in django you create a model representing an author, which has three fields - first_name, last_name and an optional field containing email. Django will also automatically add the primary-key field and call it pk (you can also decide to define your own field to use as primary key but usually don't). So when using the command manage.py syncdb it will create a table that looks like this:

+----+------------+-----------+-----------------------+
| pk | first_name | last_name | email |
+----+------------+-----------+-----------------------+

When you add a new value (say 'Stephen King') it would add it to the authors table like so:

+----+------------+-----------+-----------------------+
| pk | first_name | last_name | email |
+----+------------+-----------+-----------------------+
| 1 | Stephen | King | stephenking@gmail.com |
+----+------------+-----------+-----------------------+

Let's add another one:

+----+------------+-----------+-----------------------+
| pk | first_name | last_name | email |
+----+------------+-----------+-----------------------+
| 1 | Stephen | King | stephenking@gmail.com |
| 2 | J.D. | Salinger | |
+----+------------+-----------+-----------------------+

That's simple. Now we add a new model called Book:

+----+--------------+--------+--------+
| pk | title | genre | author |
+----+--------------+--------+--------+
| 1 | Pet Semetary | Horror | 1 |
+----+--------------+--------+--------+

Now see what I did there? at the field for author I gave book the value for Stephen King's primary key - remember, it is unique, so it will only fetch back Stephen King. That's a ForeignKey - it points to a pk on a related table, and represents a Many-To-One relationship, i.e. various books can point to the same pk of one author, but not the other way around. That way each author can have many related books, but every book has only one author.

Now let's say we want to add another book by Stephen King. This one is called The Talisman:

+----+--------------+---------+--------+
| pk | title | genre | author |
+----+--------------+---------+--------+
| 1 | Pet Semetary | Horror | 1 |
| 2 | The Talisman | Fantasy | 1 |
+----+--------------+---------+--------+

But uh oh, wait - this last one was actually co-written with another author called Peter Straub. So what do we do? We need first to add Straub to our authors table:

+----+------------+-----------+-----------------------+
| pk | first_name | last_name | email |
+----+------------+-----------+-----------------------+
| 1 | Stephen | King | stephenking@gmail.com |
| 2 | J.D. | Salinger | |
| 3 | Peter | Straub | |
+----+------------+-----------+-----------------------+

But now how do we tell the tables that The Talisman is related to two different rows? Simple - use a third table to link the two.

So table one would be authors (as seen above). second table will be books. and the third table will be called authors_books and will look like this:

+------------+--------------+
| pk_of_book | pk_of_author |
+------------+--------------+
| 1 | 1 |
| 2 | 1 |
| 2 | 3 |
+------------+--------------+

See? It tells you how to link different pks between the tables. This is a Many-To-Many relationship, because different books can be related to different authors and vice versa. And the three-table schema I described is the basic design for it.

OneToOne relationships are like ForeignKey but with a unique=True so you can only link between one object to another object and that's it. It is usually used when you want to expand a certain model without changing the original (say you want to add your own custom field to the built in User model).

Django is so wonderful that you almost never need to use SQL, but it still helps to know a little about what's happening in the background. There are plenty explanations about those relationship out in the web, I only gave you a small general intro about it, and I strongly suggest you google around a bit and expand your understanding for yourself.

one to many vs many to many relationship

The food sample does work well for a one-to-many relationship: One customer can order many dishes.

The many-to-many relationship is better described by a book sample:

An author can write many books (that would be a one-to-many relationship). But he can have co-authors also involved - one book can have many authors.

When to use ManyToOne & OneToMany vs ManyToMany

Second example:

Employees:

  1. Mohammed
  2. Bob

Tasks:

  1. Code great app
  2. Document your app

Mohammed can take several tasks (one-to-many) but now also a task can be taken by several employees (e.g. Bob can help you to do that great app).

So when you see that from one side of a relationship, it is useful a one-to-many (it is useful to assign several tasks to an employee), but also from the other side of the relationship there is value to have a one-to-many (several employees can team to do that great app), then you got a Many-to-Many.

Difference between one-to-one and one-to-many relationship in a database

In a sense, all the relationships we talk about are not known to the database, they are constructs we have invented to better understand how to design the tables.

The big difference in terms of table structure between one-to-one and one-to-many is that in one-to-one it is possible (but not necessary) to have a bidirectional relationship, meaning table A can have a foreign key into table B, and table B can have a foreign key into the associated record in table A. This is not possible with a one-to-many relationship.

One-to-one relationships associate one record in one table with a single record in the other table. One-to-many relationships associate one record in one table with many records in the other table.

Whats the difference between a OneToOne, ManyToMany, and a ForeignKey Field in Django?

Well, there's essentially two questions here:

  1. What is the difference (in general) between one to one, many to many, and foreign key relations
  2. What are their differences specific to Django.

Both of these questions are quite easily answered through a simple Google search, but as I cannot find an exact dupe of this question on SO, I'll go ahead and answer.

Note that in Django, relationships should only be defined on one side of the relationship.


ForeignKey

A foreign key relationship is generally known as a many-to-one relationship. Note that the reverse of this relationship is one-to-many (which Django provides tools to access). As the name implies, many objects may be related to one.

Person >--| Birthplace
^ ^
| |
Many One

In this example, a person may only have one birthplace, but a birthplace may be related to many people. Let's look at this example in Django. Say these are our models:

class Birthplace(models.Model):
city = models.CharField(max_length=75)
state = models.CharField(max_length=25)

def __unicode__(self):
return "".join(self.city, ", ", self.state)

class Person(models.Model):
name = models.CharField(max_length=50)
birthplace = models.ForeignKey(Birthplace)

def __unicode__(self):
return self.name

You can see that no relations are defined within the Birthplace model, and a ForeignKey relationship is defined within the Person model. Say that we create the following instances of our models (obviously not in Python syntax):

  • Birthplace: Dallas, Texas
  • Birthplace: New York City, New York
  • Person: John Smith, Birthplace : (Dallas, Texas)
  • Person: Maria Lee, Birthplace : (Dallas, Texas)
  • Person: Daniel Lee, Birthplace : (New York City, New York)

Now we can see how Django lets us use these relations (note that ./manage.py shell is your friend!):

>> from somewhere.models import Birthplace, Person
>> Person.objects.all()
[<Person: John Smith>, <Person: Maria Lee>, <Person: Daniel Lee>]
>> Birthplace.objects.all()
[<Birthplace: Dallas, Texas>, <Birthplace: New York City, New York>]

You can see the model instances we created. Now let's checkout someone's birthplace:

>> person = Person.object.get(name="John Smith")
>> person.birthplace
<Birthplace: Dallas, Texas>
>> person.birthplace.city
Dallas

Let's say you want to see all people with a given birthplace. As I said earlier, Django allows you to access reverse relations. By default, Django creates a manager (RelatedManager) on your model to handle this, named <model>_set, where <model> is your model name in lowercase.

>> place = Birthplace.objects.get(city="Dallas")
>> place.person_set.all()
[<Person: John Smith>, <Person: Maria Lee>]

Note that we can change the name of this manager by setting the related_name keyword argument in our model relation. So, we would change the birthplace field in the Person model to:

birthplace = models.ForeignKey(Birthplace, related_name="people")

Now, we can access that reverse relationship with a pretty name:

>> place.people.all()
[<Person: John Smith>, <Person: Maria Lee>]

One-to-one

A one-to-one relationship is quite similar to a many-to-one relationship, except that it restricts two objects to having a unique relationship. An example of this would be a User and a Profile (which stores information about the user). No two users share the same profile.

User |--| Profile
^ ^
| |
One One

Let's look at this in Django. I won't bother to define the user model, as Django defines it for us. Do note, however, that Django suggests using django.contrib.auth.get_user_model() to import the user, so that's what we'll do. The profile model may be defined as follows:

class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL) # Note that Django suggests getting the User from the settings for relationship definitions
fruit = models.CharField(max_length=50, help_text="Favorite Fruit")
facebook = models.CharField(max_length=100, help_text="Facebook Username")

def __unicode__(self):
return "".join(self.fruit, " ", self.facebook)

All we need is one user with a profile to test this out in the shell:

  • User: johndt6
  • Profile: user : johndt6, "Kiwi", "blah_blah"

Now you may easily access the user's profile from the User model:

>> user = User.objects.all()[0]
>> user.username
johndt6
>> user.profile
<Profile: Kiwi blah_blah>
>> user.profile.fruit
Kiwi
>> profile = Profile.objects.get(user=user)
>> profile.user
<User: johndt6>

Of course, you may customize the name of the reverse relation using the related_name argument as above.


Many-to-many

Many-to-many relationships can be a bit tricky. Let me start by saying that many-to-many fields are messy, and should be avoided when possible. Given that, there are plenty of situations where a many-to-many relationship makes sense.

A many-to-many relationship between two models defines that zero, one or more objects of the first model may be related to zero, one or more objects of the second model. As an example, let's envision a company that defines their workflow through projects. A project may be related to no orders, only one order, or many orders. An order may be related to no projects, one project, or many.

Order >--< Project
^ ^
| |
Many Many

Let's define our models as so:

class Order(models.Model):
product = models.CharField(max_length=150) # Note that in reality, this would probably be better served by a Product model
customer = models.CharField(max_length=150) # The same may be said for customers

def __unicode__(self):
return "".join(self.product, " for ", self.customer)

class Project(models.Model):
orders = models.ManyToManyField(Order)

def __unicode__(self):
return "".join("Project ", str(self.id))

Note that Django will create a RelatedManager for the orders field to access the many-to-many relationship.

Let's create the following instances of our models (in my inconsistent syntax!):

  • Order: "Spaceship", "NASA"
  • Order: "Submarine", "US Navy"
  • Order: "Race car", "NASCAR"
  • Project: orders: []
  • Project: orders: [(Order: "Spaceship", "NASA")]
  • Project: orders: [(Order: "Spaceship", "NASA"), (Order: "Race car", "NASCAR")]

We can access these relationships as follows:

>> Project.objects.all()
[<Project: Project 0>, <Project: Project 1>, <Project: Project 2>]
>> for proj in Project.objects.all():
.. print(proj)
.. proj.orders.all() # Note that we must access the `orders`
.. # field through its manager
.. print("")
Project 0
[]

Project 1
[<Order: Spaceship for NASA>]

Project 2
[<Order: Spaceship for NASA>, <Order: Race car for NASCAR>]

Note that the NASA order is related to 2 projects, and the US Navy order is related to none. Also note that one project has no orders, and one has multiple.

We may also access the relationship in reverse in the same way we have before:

>> order = Order.objects.filter(customer="NASA")[0]
>> order.project_set.all()
[<Project: Project 0>, <Project: Project 2>]

ASCII Cardinality Guide

In the likely case that my ASCII diagrams are a bit confusing, the following explanations might be helpful:

  • > or < means "to many"
  • | means "to one"

So... A --| B means an instance of A can be related to only ONE instance of B.

And A --< B means an instance of A can be related to MANY instances of B.

A >--< B is equivalent to....

A --< B
A >-- B

Thus, each "side" or direction of the relationship can be read separately. It's just convenient to squish them together.

Expanding one of these relationships might make more sense:

               +---- John Smith
|
Dallas|-------+---- Jane Doe
|
+---- Joe Smoe

Resources

Good explanation of db relationships provided by @MarcB

Wikipedia page on Cardinality

Django Docs:

models.ForeignKey

models.OneToOneField

models.ManyToManyField

One-to-one Relationships

Many-to-many Relationships

Difference between OneToMany and ManyToMany unidirectional relationships

A unidirectional OneToMany can use join columns or a join table. If it is join columns, then there is a foreign key in the target entity that can only reference a single entity. If you choose a join table, then DDL can be generated such that constraints are added to make the foreign keys to the target entity unique, enforcing a strict 1:M relationship. But they don't have to. From a JPA perspective, using a join table on a OneToMany gives it pretty much exactly the same behavior as a ManyToMany.

As for mapping a OneToMany as a OneToOne - it depends on what you mean. If your OneToMany relation was based on a foreign key existing in the target entity's table, then it is logically a OneToOne in the database going the other way. The only difference is that when building your source entity, JPA will only expect a single target entity when building the relationship. So if that foreign key in the target is not unique (ie there are many that would match), only the first is likely to be pulled up and placed in the relationship - so the relationship state will not match the actual database data. This will cause you problems when you try to manipulate the relationship directly or merge from other contexts since it could have been populated differently.

Many to Many, One to Many or Many to One

Like @Kris said - You'll go for One to Many towards middle entity. If you go for Many to Many instead then you won't have class file for middle table which is an issue in the most cases.

M-N assumption: ONE Student studies in MANY Courses and ONE COURSE can have MANY Students.

Both of the examples below give you this ERD in database but you want to go for ONE to MANY version.

Sample Image

MANY to MANY:

This will create StudentCourse entity in database but as you see no actual class file for you to deal with.

class Student
{
protected $id;
protected $name;

/**
* @ORM\ManyToMany(targetEntity="Course")
* @ORM\JoinTable(
* name="StudentCourse",
* joinColumns={@ORM\JoinColumn(name="studentId", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="courseId", referencedColumnName="id")}
* )
*/
private $course;
}

class Course
{
protected $id;
protected $name;
}

ONE TO MANY:

This will create StudentCourse entity in database and as you see there is an actual class file for you to deal with when coding e.g. persist() etc.

class Student
{
protected $id;
protected $name;

/**
* @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="studentMap",
* cascade={"persist", "remove"})
*/
protected $studentInverse;
}

class StudentCourse
{
protected $id;

/**
* @ORM\ManyToOne(targetEntity="Course", inversedBy="courseInverse")
* @ORM\JoinColumn(name="course", referencedColumnName="id",
* nullable=false, onDelete="CASCADE")
*/
protected $courseMap;

/**
* @ORM\ManyToOne(targetEntity="Student", inversedBy="studentInverse")
* @ORM\JoinColumn(name="student", referencedColumnName="id",
* nullable=false, onDelete="CASCADE")
*/
protected $studentMap;
}

class Course
{
protected $id;
protected $name;

/**
* @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="courseMap",
* cascade={"persist", "remove"})
*/
protected $courseInverse;
}

EDIT:
onDelete="CASCADE" and cascade={"persist", "remove"} bits are not compulsory. They handle data redundancy. Is it bad to use redundant relationships?



Related Topics



Leave a reply



Submit