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 oneQuestion
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 multipleQuestions
assigned to it (there will be no unique constraint in theCategory
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:
- Mohammed
- Bob
Tasks:
- Code great app
- 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:
- What is the difference (in general) between one to one, many to many, and foreign key relations
- 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.
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
Converting String to "Character" Array in Java
What Determines Kafka Consumer Offset
Arraylist or List Declaration in Java
Jpa: What Is the Proper Pattern for Iterating Over Large Result Sets
Programmatically Shut Down Spring Boot Application
What Does Class<> Mean in Java
Dealing with Randomly Generated and Inconsistent JSON Field/Key Names Using Gson
Default Fetch Type for One-To-One, Many-To-One and One-To-Many in Hibernate
Difference Between @Onetomany and @Elementcollection
What's the Correct Way to Send a File from Rest Web Service to Client
What Are the Main Uses of Yield(), and How Does It Differ from Join() and Interrupt()
Facebook Offline Access Step-By-Step
Make a File/Folder Hidden on Windows with Java
How to Convert/Parse from String to Char in Java
Difference Between List and Array
Java - JPA - @Version Annotation
What Is the Right Action to Take Upon Closing Windows in Java/Swing